Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将集合绑定到自定义控件属性_C#_Wpf_Data Binding_Collections_Custom Controls - Fatal编程技术网

C# 将集合绑定到自定义控件属性

C# 将集合绑定到自定义控件属性,c#,wpf,data-binding,collections,custom-controls,C#,Wpf,Data Binding,Collections,Custom Controls,尝试将数据集合绑定到自定义控件及其属性时,我运气不佳。我已经实现了这个控件的字符串属性的机制(这里有一个小帮助),并且希望集合类型也一样简单。然而,我不能让它再次工作 这是我的自定义控件视图 <UserControl x:Class="BadaniaOperacyjne.Controls.Matrix" mc:Ignorable="d" Name="CustomMatrix" d:DesignHeight="300" d:DesignWidt

尝试将数据集合绑定到自定义控件及其属性时,我运气不佳。我已经实现了这个控件的字符串属性的机制(这里有一个小帮助),并且希望集合类型也一样简单。然而,我不能让它再次工作

这是我的自定义控件视图

<UserControl x:Class="BadaniaOperacyjne.Controls.Matrix"
            mc:Ignorable="d" Name="CustomMatrix"
            d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.RowDefinitions>
            <!-- ... -->
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <!-- ... -->
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding ElementName=CustomMatrix, Path=Title}"/>
        <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(ObservableCollection<object>), typeof(Matrix), new PropertyMetadata(new ObservableCollection<object>(), new PropertyChangedCallback(ItemsListChanged)));
public ObservableCollection<object> ItemsList
{
    get { return GetValue(ItemsListProperty) as ObservableCollection<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)
{
    // a breakpoint
    ((Matrix)d).ItemsListChanged(e.NewValue);
}
#endregion

// showing the Title property implementation just to state that
// it is done the same way as for ItemsList
#region Title Property
public static readonly DependencyProperty TitleProperty = 
    DependencyProperty.Register("Title", typeof(string), typeof(Matrix), new PropertyMetadata("", new PropertyChangedCallback(TitleChanged)));
public string Title
{
    get { return (string)GetValue(TitleProperty); }
    set { SetValue(TitleProperty, value); }
}
private void TitleChanged(string title)
{
    System.Diagnostics.Debug.WriteLine("matrix: title changed to: " + title);
}
private static void TitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ((Matrix)d).TitleChanged((string)e.NewValue);
}
#endregion
#区域项目列表属性
公共静态只读从属属性ItemsListProperty=
DependencyProperty.Register(“ItemsList”、typeof(ObservableCollection)、typeof(Matrix)、new PropertyMetadata(new ObservableCollection()、new PropertyChangedCallback(ItemsListChanged));
公共可观测收集项目列表
{
获取{返回GetValue(ItemsListProperty)作为ObservableCollection;}
set{SetValue(ItemsListProperty,value);}
}
私有void ItemsListChanged(对象值)
{
System.Diagnostics.Debug.WriteLine(“矩阵:项目列表已更改”+值);
if(ItemsList!=null)
{
ItemsList.CollectionChanged+=ItemsList\u CollectionChanged;
System.Diagnostics.Debug.WriteLine(“got”+string.Join(“,”,ItemsList.ToList());
}
其他的
{
System.Diagnostics.Debug.WriteLine(“获取空值”);
}
}
void ItemsList\u CollectionChanged(对象发送方,System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
System.Diagnostics.Debug.WriteLine(“矩阵:当前项列表集合已更改”);
}
私有静态无效项列表已更改(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
//断点
((矩阵)d).项目已更改(如新值);
}
#端区
//显示Title属性实现只是为了说明
//它的执行方式与ItemsList相同
#区域所有权财产
public static readonly dependencProperty TitleProperty=
DependencyProperty.Register(“Title”,typeof(string),typeof(Matrix),newpropertyMetadata(“,newpropertyChangedCallback(TitleChanged));
公共字符串标题
{
获取{return(string)GetValue(TitleProperty);}
set{SetValue(TitleProperty,value);}
}
私有无效标题更改(字符串标题)
{
System.Diagnostics.Debug.WriteLine(“矩阵:标题更改为:“+标题”);
}
私有静态无效标题已更改(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
((矩阵)d).标题更改((字符串)e.新值);
}
#端区
下面是我如何尝试绑定到该控件

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

主页背后的代码是

//internal ObservableCollection<List<int>> ItemsList { get; set; }
public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

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

    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; 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; }

// this is the window constructor
private ProblemManager() 
{
    VM = new ViewModel();

    DataContext = VM;
    InitializeComponent();

    VM.Title = "title";
}

private int i = 0;
private void btnAddRow_Click(object sender, RoutedEventArgs e)
{
    // when doing either of these two lines below, 
    // the control breakpoint is never hit
    VM.Items.Add(++i);
    VM.Items = new ObservableCollection<int> { 2, 3 };

    // however, when directly assigning to the control's property, 
    // the event is raised and the breakpoint is hit and the UI is updated
    customMatrix.ItemsList = new ObservableCollection<object> { 1, 2, 3 };
    customMatrix.ItemsList.Add(66);
    // and this of course makes the control's title update
    VM.Title = (++i).ToString();
}
//内部ObservableCollection项列表{get;set;}
公共类视图模型:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
公共视图模型()
{
项目=新的可观察集合{1,2,3,4,5,6};
}
无效项\u CollectionChanged(对象发送方,System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
System.Diagnostics.Debug.WriteLine(“问题管理器:项目列表已更改”+e.NewItems.Count);
}
公共ObservableCollection项{get;set;}
受保护的字符串标题;
公共字符串标题
{
获取{返回标题;}
设置
{
如果(标题!=值)
{
标题=价值;
通知财产变更(“所有权”);
}
}
}
受保护的void NotifyPropertyChanged(字符串名称)
{
PropertyChangedEventHandler处理程序=PropertyChanged;
if(处理程序!=null)
{
处理程序(此,新PropertyChangedEventArgs(名称));
}
}
}
公共视图模型VM{get;private set;}
//这是窗口构造函数
私人问题经理()
{
VM=新的ViewModel();
DataContext=VM;
初始化组件();
VM.Title=“Title”;
}
私有整数i=0;
私有无效btnAddRow_单击(对象发送者,路由目标e)
{
//在执行下面两行中的任何一行时,
//永远不会命中控件断点
VM.Items.Add(++i);
VM.Items=新的可观测集合{2,3};
//但是,当直接指定给控件的属性时,
//引发事件并命中断点并更新UI
customMatrix.ItemsList=新的ObservableCollection{1,2,3};
customMatrix.ItemsList.Add(66);
//这当然会使控件的标题更新
VM.Title=(++i.ToString();
}
我相信,控件的
标题
项目列表
dependencProperty
都是以相同的方式创建的。尽管如此,该绑定可能不起作用,因为该绑定未引发
ItemsListChanged
事件。
因此,问题是我无法通过XAML将窗口的
ViewModel.Items
集合绑定到控件的
ItemsList
集合。为控件内的集合创建
dependencProperty
是否与为简单
字符串
属性创建
dependencProperty
不同?

问题在于
dependencProperty
注册<代码>协方差不适用于通用列表
,即您不能这样做-

ObservableCollection<object> objects = new ObservableCollection<int>();
ObservableCollection对象=新的ObservableCollection();
您已将DP的类型声明为
observedcollection
,但将其与
observedcollection
类型列表绑定

您应该
将DP类型更改为ObservableCollection
将绑定集合类型更改为ObservableCollection

公共视图模型()
{
项目=新的可观察集合{1,2,3,4,5,6};
}
公共ObservableCollection项{get;set;}

经过这么长时间,我需要这两种方法:

  • 能够定义任何类型项目的集合public ViewModel() { Items = new ObservableCollection<object> { 1, 2, 3, 4, 5, 6}; } public ObservableCollection<object> Items { get; set; }
  • public static readonly DependencyProperty ItemsSourceProperty =
      DependencyProperty.Register("ItemsSource", typeof(IList), typeof(BreadCrumbUserControl), 
        new PropertyMetadata(null, new PropertyChangedCallback(OnItemsSourceChanged)));
    
    <views:BreadCrumbUserControl ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}"/>
    
    public ObservableCollection<BaseItem> Items { get; set; }
    
    private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      BreadCrumbUserControl thisUserControl = (BreadCrumbUserControl)d;
      (e.NewValue as INotifyCollectionChanged).CollectionChanged += thisUserControl.BreadCrumbUserControl_CollectionChanged;
    }
    
    foreach (var baseItem in ItemsSource)
    {
       baseItem.GetType().GetProperty("IsActive").SetValue(baseItem, false);
    }