2016-12-01 66 views
2

我試圖將用戶控件屬性「MyUserControl.Names」綁定到主窗口的集合屬性「名稱」。如果我在ItemsControl模板中執行它,它不起作用,但如果我將控件定義移出ItemsControl模板,它將起作用。這裏是XAML:無法綁定到來自ItemsControl模板的集合

<Window x:Class="TestItemsControl.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:TestItemsControl" 
     Height="200" Width="200" 
     Name="MainControl"> 
    <StackPanel> 
     <ItemsControl ItemsSource="{Binding Groups, ElementName=MainControl}"> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <!-- This doesn't work --> 
        <StackPanel Background="WhiteSmoke" Height="40" Width="100" Margin="5" HorizontalAlignment="Left"> 
         <TextBlock Text="{Binding .}"/> 
         <local:MyUserControl Names="{Binding Names, ElementName=MainControl}"/> 
        </StackPanel> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl> 
     <!-- This works --> 
     <StackPanel Background="WhiteSmoke" Height="40" Width="100" Margin="5" HorizontalAlignment="Left"> 
      <TextBlock Text="Group3"/> 
      <local:MyUserControl Names="{Binding Names, ElementName=MainControl}"/> 
     </StackPanel> 
    </StackPanel> 
</Window> 

MainWindow.xaml.cs包含兩個依賴屬性:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     SetValue(GroupsProperty, new ObservableCollection<string>()); 
     SetValue(NamesProperty, new ObservableCollection<string>()); 

     Groups.Add("Group1"); 
     Groups.Add("Group2"); 
     Names.Add("Name1"); 
     Names.Add("Name2"); 
    } 

    public static readonly DependencyProperty GroupsProperty = 
     DependencyProperty.Register("Groups", typeof(ObservableCollection<string>), typeof(MainWindow), 
     new PropertyMetadata(null)); 

    public ObservableCollection<string> Groups 
    { 
     get { return (ObservableCollection<string>)GetValue(GroupsProperty); } 
     set { SetValue(GroupsProperty, value); } 
    } 

    public static readonly DependencyProperty NamesProperty = 
     DependencyProperty.Register("Names", typeof(ObservableCollection<string>), typeof(MainWindow), 
     new PropertyMetadata(null)); 

    public ObservableCollection<string> Names 
    { 
     get { return (ObservableCollection<string>)GetValue(NamesProperty); } 
     set { SetValue(NamesProperty, value); } 
    } 
} 

下面是結果:

enter image description here

前兩個矩形是什麼的ItemsControl產生。第三個是我在ItemsControl後手動添加的東西。正如你所看到的,即使代碼在兩種情況下都是完全相同的,前兩個矩形沒有名字,但是第三個有。有什麼理由不能用於ItemsControl?

編輯:

這裏是MyUserControl.xaml.cs的代碼:

public partial class MyUserControl : UserControl 
{ 
    public MyUserControl() 
    { 
     InitializeComponent(); 
     SetValue(NamesProperty, new ObservableCollection<string>()); 
    } 

    public static readonly DependencyProperty NamesProperty = DependencyProperty.Register(
     "Names", typeof(ObservableCollection<string>), typeof(MyUserControl), 
     new PropertyMetadata(null, NamesPropertyChanged)); 

    public ObservableCollection<string> Names 
    { 
     get { return (ObservableCollection<string>)GetValue(NamesProperty); } 
     set { SetValue(NamesProperty, value); } 
    } 

    private static void NamesPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     var control = (MyUserControl)obj; 
     var oldCollection = e.OldValue as INotifyCollectionChanged; 
     var newCollection = e.NewValue as INotifyCollectionChanged; 

     if (oldCollection != null) 
      oldCollection.CollectionChanged -= control.NamesCollectionChanged; 
     if (newCollection != null) 
      newCollection.CollectionChanged += control.NamesCollectionChanged; 

     control.UpdateNames(); 
    } 

    private void NamesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     UpdateNames(); 
    } 

    private void UpdateNames() 
    { 
     NamesPanel.Children.Clear(); 

     if (Names == null) 
      return; 

     foreach(var name in Names) 
     { 
      var textBlock = new TextBlock(); 
      textBlock.Text = name + ", "; 
      NamesPanel.Children.Add(textBlock); 
     } 
    } 
} 

MyUserControl.xaml:

<UserControl x:Class="TestItemsControl.MyUserControl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:TestItemsControl" 
      mc:Ignorable="d" 
      d:DesignHeight="300" 
      d:DesignWidth="300" 
      Name="ParentControl"> 
    <StackPanel Name="NamesPanel" Orientation="Horizontal"/> 
</UserControl> 

回答

2

通過SetCurrentValue更換SetValue在用戶控件的構造。對於Names屬性,根本不需要分配初始值。

public MyUserControl() 
{ 
    InitializeComponent(); 
    SetCurrentValue(NamesProperty, new ObservableCollection<string>()); 
} 

SetValue(相對於SetCurrentValue)設置一個所謂的局部值到Names屬性。當你像第二種情況那樣分配綁定時,這也被認爲是一個與構造函數中設置的優先級相同的本地值。

但是,在第一種情況下,綁定是在DataTemplate中設置的,它不被視爲本地值。由於它具有較低的優先級,因此它不會取代初始值。

更多細節在這裏:Dependency Property Value Precedence

相關問題