2016-04-13 9 views
1

I, wie in diesem Thread das gleiche Problem habe.Bind Eigenschaft Usercontrol

Ich habe gelesen, dies auch article aber ich kann den Grund nicht finden, warum bekomme ich diese Ausnahme haben:

enter image description here

ich ein Usercontrol nenne, in dem ein anderes Usercontrol aufgerufen werden soll.

Innerhalb der ersten Usercontrol Ich werde die folgende

<UserControl 
x:Class="TwitterUniversalHubTest1.UCGlobalTweet" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="using:TwitterUniversalHubTest1" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d" 
d:DesignHeight="150" 
d:DesignWidth="400"> 

<Grid Height="Auto"> 
    <Border Background="#FFFFFFFF" Margin="10 0 0 5" CornerRadius="2 2 15 2"> 
     <Grid Width="380"> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="Auto"/> 
       <RowDefinition Height="*"/> 
      </Grid.RowDefinitions> 
      <StackPanel Tag="{Binding UserID}" Grid.Row="0" Name="ProfileInfo" Tapped="Profile_Tapped" Orientation="Horizontal" Margin="15 15 15 0"> 
       <Grid Width="360" Margin="0 0 0 10"> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="75"></ColumnDefinition> 
         <ColumnDefinition Width="*"></ColumnDefinition> 
         <ColumnDefinition Width="50"></ColumnDefinition> 
        </Grid.ColumnDefinitions> 
        <Border Grid.Column="0" Height="45" Width="45" CornerRadius="5"> 
         <Border.Background> 
          <ImageBrush ImageSource="{Binding ImagePath}" Stretch="UniformToFill"/> 
         </Border.Background> 
        </Border> 
        <StackPanel Grid.Column="1" Orientation="Vertical" Margin="0 5 0 0"> 
         <TextBlock Text="{Binding FullName}" Foreground="Black" FontSize="18" FontWeight="Bold"></TextBlock> 
         <TextBlock Text="{Binding TwitterHandle}" Foreground="DarkGray" FontSize="12"/> 
        </StackPanel> 
        <Image Grid.Column="2" Source="Assets/ActionIcons/Twitter_logo_blue_32.png" Width="32" VerticalAlignment="Top"></Image> 
       </Grid> 
      </StackPanel> 

      <StackPanel Grid.Row="1" Margin="14.5,0,0,0" Height="Auto"> 

       <StackPanel Name="TwContent" Tag="{Binding TweetID}" Margin="15 0 15 0" Tapped="Content_Tapped"> 

        <local:ComplexTextPresenter x:Name="ComplexTextPresenterElement" Input="{Binding Content}" DataContext="{Binding Content}"/> 
        <ItemsControl ItemsSource="{Binding ContentImages}"> 
         <ItemsControl.ItemTemplate> 
          <DataTemplate> 
           <Image Source="{Binding }" MaxWidth="350" Margin="0 0 0 5" HorizontalAlignment="Center"></Image> 

          </DataTemplate> 
         </ItemsControl.ItemTemplate> 
        </ItemsControl> 
        <TextBlock Foreground="DarkGray" Text="{Binding DateSend}" FontSize="10"></TextBlock> 
       </StackPanel> 
       <StackPanel Name="ActionButtons"> 
        <Grid Tag="{Binding TweetID}" Width="380" Height="25" Margin="0 0 0 10"> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition Width="*"/> 
          <ColumnDefinition Width="*"/> 
          <ColumnDefinition Width="*"/> 
          <ColumnDefinition Width="*"/> 
          <ColumnDefinition Width="*"/> 
          <ColumnDefinition Width="*"/> 
         </Grid.ColumnDefinitions> 

         <Button Grid.Column="0" HorizontalAlignment="Center" Margin="20 0 0 0" Style="{StaticResource replyActionButton}" Tapped="Reply_Tapped"></Button> 

         <ToggleButton Grid.Column="2" HorizontalAlignment="Center" Style="{StaticResource retweetActionButton}" Tapped="Retweet_Tapped"></ToggleButton> 
         <TextBlock Grid.Column="3" HorizontalAlignment="Left" Margin="-15 0 0 0" VerticalAlignment="Center" Text="{Binding RetweetCount}" Foreground="DarkGray"/> 

         <ToggleButton x:Name="FavButton" Grid.Column="4" HorizontalAlignment="Center" 
              Style="{StaticResource likeActionButton}" 
              IsChecked="{Binding LikeState}" 
              Tapped="Favourite_Tapped"/> 
         <TextBlock Grid.Column="5" HorizontalAlignment="Left" Margin="-15 0 0 0" VerticalAlignment="Center" Text="{Binding LikeCount}" Foreground="DarkGray"/> 
        </Grid> 
       </StackPanel> 
      </StackPanel> 
     </Grid> 
    </Border> 
</Grid> 

Die Content-Eigenschaft in Input="{Binding Content}" ist eine Zeichenfolge tun wollen.

Das Problem tritt mit der Eingangs Eigenschaft binden. Die Bindung in ItemsControl funktioniert einwandfrei. Da die Ausnahmen beschreibt in Linie die Bindung: 43 Position: 90.

Die Code-Behind für die ComplexTextPresenterElement wie folgt aussieht:

public static readonly DependencyProperty InputProperty = DependencyProperty.Register("Input", typeof(string), typeof(UCGlobalTweet), new PropertyMetadata(default(string), InputPropertyChangedCallback)); 

private static void InputPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) 
{ 
    var ctrl = dependencyObject as ComplexTextPresenter; 
    if (ctrl == null) 
     return; 
    ctrl.Init(); 
} 

public static readonly DependencyProperty InputCollectionProperty = DependencyProperty.Register("InputCollection", typeof(ObservableCollection<object>), typeof(UCGlobalTweet), new PropertyMetadata(default(ObservableCollection<object>))); 
public static readonly DependencyProperty OnHyperlinkCommandProperty = DependencyProperty.Register("OnHyperlinkCommand", typeof(ICommand), typeof(UCGlobalTweet), new PropertyMetadata(default(ICommand))); 

private IEnumerable<object> GetParsedInput() 
{ 
    List<BaseInputPart> inputParts = new List<BaseInputPart>(); 
    var strings = Input.Split(new[] { " " }, StringSplitOptions.None).ToList(); 

    foreach (var s in strings) 
    { 
     if (s.IsHyperlink()) 
     { 
      inputParts.Add(new HyperLinkPart { Content = s }); 
     } 
     else 
     { 
      inputParts.Add(new LiteralPart { Content = s }); 
     } 
    } 
    return inputParts.OfType<object>().ToList(); 
} 

public string Input 
{ 
    get { return (string)GetValue(InputProperty); } 
    set { SetValue(InputProperty, value); } 
} 

public ObservableCollection<object> InputCollection 
{ 
    get { return (ObservableCollection<object>)GetValue(InputCollectionProperty); } 
    private set { SetValue(InputCollectionProperty, value); } 
} 

public ICommand OnHyperlinkCommand 
{ 
    get { return (ICommand)GetValue(OnHyperlinkCommandProperty); } 
    set { SetValue(OnHyperlinkCommandProperty, value); } 
} 

private void Init() 
{ 
    InputCollection = new ObservableCollection<object>(GetParsedInput()); 
} 

public ComplexTextPresenter() 
{ 
    this.InitializeComponent(); 
} 


public abstract class BaseInputPart 
{ 
    public abstract string Content { get; set; } 
} 

public class HyperLinkPart : BaseInputPart 
{ 
    public override string Content { get; set; } 
} 

public class LiteralPart : BaseInputPart 
{ 
    public override string Content { get; set; } 
} 

// UPDATE: Dies ist die UCGlobalTweet.xaml.cs

public sealed partial class UCGlobalTweet : UserControl 
{ 
    private readonly NavigationHelper navigationHelper; 
    private readonly ObservableDictionary defaultViewModel = new ObservableDictionary(); 
    private readonly ResourceLoader resourceLoader = ResourceLoader.GetForCurrentView("Resources"); 

    //passingparameter 
    public string MyContentProperty { get; set; } 

    public UCGlobalTweet() 
    { 
     this.InitializeComponent(); 
     Init(); 
    } 

    private void Init() 
    { 

     ComplexTextPresenterElement.Input = "This is where the Content string has to be...."; 
     ComplexTextPresenterElement.OnHyperlinkCommand = new RelayCommand<object>(Execute); 
    } 

    private void Execute(object o) 
    { 
     //put here the code that can open browser 
    } 

    public ObservableDictionary DefaultViewModel 
    { 
     get { return this.defaultViewModel; } 
    } 

    // Tap user specific content 
    private void Profile_Tapped(object sender, TappedRoutedEventArgs e) 
    { 
     Debug.WriteLine("I've clicked on information from Profile --> UserInfoPage"); 
     List<object> passingParameters = new List<object>(); 

     StackPanel st = (StackPanel)sender; 
     string userIDList = (string)st.Tag; 

     //provisional Data transfer 
     // get UserObject out of SearchResult, therefore I have to put the user content as a global variable to access it here, but this will require a lot of space probably... 
     // So for now I recall the UserObject again. 

     var usersResponse = 
       (from user in TweetContent.Connection.User 
       where user.Type == UserType.Lookup && 
         user.UserIdList == userIDList 
       //user.ScreenNameList == "JoeMayo,Linq2Tweeter" 
       select user).ToList(); 

     User curUser = usersResponse.FirstOrDefault(); 
     passingParameters.Add(curUser); 

     (Window.Current.Content as Frame).Navigate(typeof(UserInfoPage), passingParameters); 
    } 

    // Tap tweet specific content 
    private void Content_Tapped(object sender, TappedRoutedEventArgs e) 
    { 
     Debug.WriteLine("I've clicked the Tweet content --> Going to TweetInfoPage"); 
     List<object> passingParameters = new List<object>(); 

     StackPanel ContentTapped = (StackPanel)sender; 
     ulong tag = (ulong)ContentTapped.Tag; 
     var test = TweetContent.FulltweetList; 
     var tweet = test.FirstOrDefault(tw => tw.TweetID == tag); 

     passingParameters.Add(tweet); 


     (Window.Current.Content as Frame).Navigate(typeof(TweetInfoPage), passingParameters); 

    } 

    //Action Buttons 
    private void Reply_Tapped(object sender, TappedRoutedEventArgs e) 
    { 
     Debug.WriteLine("Reply Button Tapped"); 
     var test = (Button)sender; 

     e.Handled = true; 
     Debug.WriteLine("New State for Reply: " + test.IsPressed); 
    } 

    private void Retweet_Tapped(object sender, TappedRoutedEventArgs e) 
    { 
     Debug.WriteLine("Retweet Button Tapped"); 
     //var test = (Button)sender; 

     //e.Handled = true; 
     //Debug.WriteLine("New State for Retweet: " + test.IsPressed); 
    } 

    private async void Favourite_Tapped(object sender, TappedRoutedEventArgs e) 
    { 
     try 
     { 
      Debug.WriteLine("Favourite Button Tapped"); 
      ToggleButton tBtn = (ToggleButton)sender; 
      Grid pGrid = (Grid)tBtn.Parent; 
      var curTweet = TweetContent.FulltweetList.Where(tw => tw.TweetID.Equals(pGrid.Tag)); 

      if (tBtn.IsChecked == false) 
      { 
       Debug.WriteLine("Status should be Checked: " + tBtn.IsChecked); 
       await TweetContent.Connection.DestroyFavoriteAsync((ulong)pGrid.Tag); 
       curTweet.First().LikeCount--; 
      } 

      if (tBtn.IsChecked == true) 
      { 
       Debug.WriteLine("Status should be UnChecked: " + tBtn.IsChecked); 
       await TweetContent.Connection.CreateFavoriteAsync((ulong)pGrid.Tag); 
       curTweet.First().LikeCount++; 
      } 
     } 
     catch (Exception ex) 
     { 
      Debug.WriteLine("Error while updating Favourite State: Message: " + ex); 
     } 
     finally 
     { 
      e.Handled = true; 
     } 
    } 

    private void RealLink_Clicked(object sender, RoutedEventArgs e) 
    { 
     var hyperlink = sender as Hyperlink; 
     if (hyperlink == null) return; 
     //Process.Start(hyperlink.NavigateUri.AbsoluteUri); 
    } 

} 

Und hier kommt die ComplexTextPresenter.xaml - die zweite Usercontrol, die ich von

sprechen
<UserControl 
x:Class="TwitterUniversalHubTest1.ComplexTextPresenter" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:ts="using:TwitterUniversalHubTest1" 
xmlns:panel="using:Gregstoll" 
mc:Ignorable="d" 
d:DesignHeight="300" 
d:DesignWidth="400" x:Name="This"> 
<Grid> 
    <Grid.Resources> 
     <DataTemplate x:Key="HyperlinkDataTemplateKey"> 
      <HyperlinkButton Padding="0" Margin="0" FontSize="12" CommandParameter="{Binding }" Command="{Binding ElementName=This, Path=OnHyperlinkCommand}" Content="{Binding Path=Content}" Foreground="Blue"/> 
     </DataTemplate> 
     <DataTemplate x:Key="LiteralDataTemplateKey"> 
      <TextBlock Padding="0" Margin="0" FontSize="12" Text="{Binding Path=Content}"></TextBlock> 
     </DataTemplate> 
     <ts:MyDataTemplateSelector x:Key="DataTemplateSelectorKey" 
           LiteralDataTemplate ="{StaticResource LiteralDataTemplateKey}" 
           HyperlinkDataTemplate="{StaticResource HyperlinkDataTemplateKey}"/> 
     <Style TargetType="ListBoxItem"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate> 
         <ContentPresenter HorizontalAlignment="Left" VerticalAlignment="Center" Margin="5,0,0,0"/> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </Grid.Resources> 
    <!--<Rectangle Fill="Green" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>--> 
    <ListBox Margin="-5 0 0 15" Foreground="Black" ItemsSource="{Binding ElementName=This, Path=InputCollection}" ItemTemplateSelector="{StaticResource DataTemplateSelectorKey}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <panel:UniversalWrapPanel Orientation="Horizontal"/> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
    </ListBox> 
</Grid> 

Cheers, Ulpin

+0

Was ist der 'DataContext' der Bindung? –

+0

Ich bin kein Wert in dem 'DataContext' – Ulpin

+0

setze Aber es muss ein Wert in dem' DataContext' sein, um die Bindung der Arbeit zu machen, oder Sie müssen explizit die 'Source' oder die' ElementName' darauf hinzuweisen, statt . –

Antwort

1

Wenn Sie Ihre Eigenschaften registrieren Sie den Typ der Klasse übergeben sollte, die die Eigenschaften enthält, aber Sie sind vorbei typeof(UCGlobalTweet) statt. Sie sollten es so machen:

class ComplexTextPresenterElement 
{ 
    public static readonly DependencyProperty InputProperty = DependencyProperty.Register("Input", typeof(string), typeof(ComplexTextPresenterElement), new PropertyMetadata(default(string), InputPropertyChangedCallback));  
    public static readonly DependencyProperty InputCollectionProperty = DependencyProperty.Register("InputCollection", typeof(ObservableCollection<object>), typeof(ComplexTextPresenterElement), new PropertyMetadata(default(ObservableCollection<object>))); 
    public static readonly DependencyProperty OnHyperlinkCommandProperty = DependencyProperty.Register("OnHyperlinkCommand", typeof(ICommand), typeof(ComplexTextPresenterElement), new PropertyMetadata(default(ICommand))); 
} 
+0

Danke. Das scheint zu funktionieren. Ich habe stundenlang mit diesen drei Zeilen Code gespielt und konnte es nicht herausfinden. Aber immer noch ist die Bindung nicht korrekt. Ich erhalte keinen Fehler mehr, aber der Inhalt wird nicht angezeigt, stattdessen gibt es 'Windows.UI.Xaml.Controls.Grid' ... Hast du eine Idee, worum es geht? – Ulpin

+0

Im Code-Behind des UCGlobalTweet userControls mache ich die Berechnungen, um die Content-Zeichenfolge aus der Bindung vorzubereiten. Ich denke, dass etwas an der Init() Funktion falsch ist, weil die ComplexTextPresenterElement Instanz zu diesem Zeitpunkt nicht initialisiert ist, deshalb habe ich etwas mit dem var test = [...] – Ulpin

+0

@Ulpin Tut mir leid, ich kann dir nicht ohne helfen der komplette Quellcode –

1

Es gibt keine DataContext, ElementName noch Source in Ihre Bindungen. Es gibt mehrere Ansätze, um den Code arbeiten zu lassen, ich werde Ihnen die einfachsten geben, die Sie auswählen können.

1) Stellen Sie die DataContext Ihrer UserControl auf {Binding RelativeSource={RelativeSource Self}}. Das ist ein schlechter Ansatz aber, wie Sie die vorhandenen DataContext überschreiben können oder haben sie aus dem externen Code überschreiben.

2) Benennen Sie Ihre UserControl und binden es ElementName verwenden.

Input="{Binding Content, ElementName=userControl}" 

3) Verwenden Sie {x:Bind}:

Input="{x:Bind Content}" 
+0

Ok. Ich werde es versuchen. Warum funktionieren die anderen Bindungen im UserControl? Was ist der Unterschied bei der Bindung an ein anderes UserControl? – Ulpin

+0

@Ulpin Jedes Steuerelement in 'DataTemplate' hat' DataContext' implizit auf das aktuelle Element gesetzt. Außerdem kann Ihr 'UserControl'' DataContext' aus dem externen Code setzen (wie es ein 'UserControl' ist). –

+0

@Ulpin Verwenden Sie '{x: Bind}', es ist die beste Lösung für Sie. Ich habe die Antwort aktualisiert, sieh es dir an. –

Verwandte Themen