2013-12-07 38 views
0

有了一些帮助,我最近在自定义控件工作中制作了绑定集合。然而,令我惊讶的是,我被告知为了使自定义控件属性更加灵活(可以与其他参数化集合绑定),我需要使自定义控件的属性为IEnumerable<object>,因为协变和逆变。不过,这似乎并不为我将自定义控件的ObservableCollection <int>绑定到IEnumerable <object>

工作时,此控件的视图

<UserControl x:Class="BadaniaOperacyjne.Controls.Matrix" 
      mc:Ignorable="d" Name="CustomMatrix" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <Grid> 
      <!-- ... --> 
     <Grid Grid.Row="2" Grid.Column="1" Name="contentGrid"> 
      <ListBox ItemsSource="{Binding ElementName=CustomMatrix, Path=ItemsList}"> 
       <ListBox.ItemTemplate> 
        <DataTemplate> 
         <TextBlock Text="{Binding}"/> 
        </DataTemplate> 
       </ListBox.ItemTemplate> 
      </ListBox> 
     </Grid> 
    </Grid> 
</UserControl> 

及其代码隐藏在这里

#region ItemsList Property 
public static readonly DependencyProperty ItemsListProperty = 
    DependencyProperty.Register("ItemsList", typeof(IEnumerable<object>), typeof(Matrix), new PropertyMetadata(new PropertyChangedCallback(ItemsListChanged))); 
public IEnumerable<object> ItemsList 
{ 
    get { return GetValue(ItemsListProperty) as IEnumerable<object>; } 
    set { SetValue(ItemsListProperty, value); } 
} 
private void ItemsListChanged(object value) 
{ 
    System.Diagnostics.Debug.WriteLine("matrix: items list changed " + value); 
    if (ItemsList != null) 
    { 
     //ItemsList.CollectionChanged += ItemsList_CollectionChanged; 
     System.Diagnostics.Debug.WriteLine("got " + string.Join(",", ItemsList.ToList())); 
    } 
    else 
    { 
     System.Diagnostics.Debug.WriteLine("got null"); 
    } 
} 

void ItemsList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
{ 
    System.Diagnostics.Debug.WriteLine("matrix: current items list collection changed"); 
} 
private static void ItemsListChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    ((Matrix)d).ItemsListChanged(e.NewValue); 
} 
#endregion 

和消耗的控制窗口的下面

<custom:Matrix x:Name="customMatrix" DockPanel.Dock="Top" Title="{Binding Title}" ItemsList="{Binding Items}"/> 

与代码隐藏如

public class ViewModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    public ViewModel() 
    { 
     Items = new ObservableCollection<int> { 1, 2, 3, 4, 5, 6}; 

     Items.CollectionChanged += Items_CollectionChanged; 
    } 

    void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine("problem manager: items list changed " + e.NewItems.Count); 
    } 

    public ObservableCollection<int> Items { get; private set; } 

    protected string title; 
    public string Title 
    { 
     get { return title; } 
     set 
     { 
      if (title != value) 
      { 
       title = value; 
       NotifyPropertyChanged("Title"); 
      } 
     } 
    } 

    protected void NotifyPropertyChanged(string name) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
} 

public ViewModel VM { get; private set; } 

// the window's constructor 
private ProblemManager() 
{ 
    VM = new ViewModel(); 

    DataContext = VM; 
    InitializeComponent(); 

    VM.Title = "title"; 
} 

private int i = 0; 
private void btnAddRow_Click(object sender, RoutedEventArgs e) 
{ 
    //VM.Items.Add(++i); 
    VM.Items[2] = 112; 
    //customMatrix.ItemsList = new ObservableCollection<object> { 1, 2, 3 }; 
    //customMatrix.ItemsList.Add(66); 
    ////// 
    VM.Title = (++i).ToString(); 
} 

当我改变ItemsList控制的DependencyPropertyObservableCollection<int>或至少ObservableCollection<object>,它工作正常。 真的有可能吗?如果是这样,那么我犯的错误是什么?

+0

不'ItemsListChanged'被调用? –

+0

删除所有的代码并使用'ItemsControl'。不要试图重新发明轮子。它已经被发明了。 –

+0

它没有。这对我来说很奇怪,当然需要解释或指出我的错误。 @HighCore我不是想实现一个列表,而是更复杂的事情的开始。然而,在解决将集合绑定到自定义控件的问题时,我被告知这是让集合绑定更加灵活的方式,我无法完成这项工作。 – patryk

回答

0

Co-variance允许用于IEnumerable但我只检查了它的唯一allowed for reference types and not for value types (e.g. int)

string is reference type开始,您的版本将与ObservableCollection<string>绑定。

所以你可以做的是使用IEnumerable (non-generic version)为您的DP这样的返回类型,这样它会值类型以及工作:

public static readonly DependencyProperty ItemsListProperty = 
    DependencyProperty.Register("ItemsList", typeof(IEnumerable), typeof(Matrix), 
     new PropertyMetadata(new PropertyChangedCallback(ItemsListChanged))); 

public IEnumerable ItemsList 
{ 
    get { return (IEnumerable)GetValue(ItemsListProperty); } 
    set { SetValue(ItemsListProperty, value); } 
} 
+0

使用IEnumerable作为控件的属性类型最终使它工作。谢谢! – patryk

+0

您的欢迎patryk .. :) –

相关问题