2013-12-07 69 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 .. :) –

相關問題