简体   繁体   English

绑定一个ObservableCollection <int> 到IEnumerable <object> 自定义控件

[英]Binding a ObservableCollection<int> to IEnumerable<object> of a custom control

With some help, I recently made binding collections in my custom control work. 在一些帮助下,我最近在我的自定义控件工作中进行了绑定集合。 However, to my surprise I was told that to make the custom control property more flexible (that is possible to be bound with other parametrized collections), I needed to make the custom control's property to be of type IEnumerable<object> because of covariance and contravariance. 但是,令我惊讶的是,我被告知要使自定义控件的属性更加灵活(可以与其他参数化集合绑定),由于协方差和自变量,我需要使自定义控件的属性的类型为IEnumerable<object> 。逆变。 However, this seems not to work for me 但是,这似乎对我不起作用

This is the control's view 这是控件的视图

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

and its code-behind is here 它的代码在这里

#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

and the Window that consumes the control is the following 使用该控件的窗口如下

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

with the code-behind like 与背后的代码一样

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

When I change the DependencyProperty of the ItemsList control to ObservableCollection<int> or at least ObservableCollection<object> , it works fine. 当我将ItemsList控件的DependencyProperty更改为ObservableCollection<int>或至少更改为ObservableCollection<object> ,它可以正常工作。 Is it really possible? 真的有可能吗? If so, then is the mistake I made? 如果是这样,那我犯了错误吗?

Co-variance is allowed for IEnumerable but i just checked its only allowed for reference types and not for value types (eg int) . IEnumerable允许IEnumerable Co-variance ,但是我只是检查了它仅allowed for reference types and not for value types (eg int)

Your version will work if you bind with ObservableCollection<string> since string is reference type . 如果您与ObservableCollection<string>绑定,则您的版本将可用,因为string is reference type

So what you can do is use IEnumerable (non-generic version) as return type of your DP like this so that it will work for value types as well: 因此,您可以做的是像这样将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); }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用ObservableCollection的自定义控件绑定 - custom control binding with ObservableCollection 从自定义控件绑定到ObservableCollection - Binding to ObservableCollection from Custom Control 在自定义用户控件中绑定 ObservableCollection - Binding ObservableCollection in Custom User Control 绑定一个ObservableCollection <int> 到标签 - Binding an ObservableCollection<int> to a Label 将 IEnumerable 转换为自定义 ObservableCollection 类? - Cast IEnumerable to custom ObservableCollection Class? 字典 <int, ObservableCollection<Entity> &gt;装订 - Dictionary<int, ObservableCollection<Entity>> Binding 检查IEnumerable <object>是否为IEnumerable <int> - Check if IEnumerable<object> is IEnumerable<int> 为什么`IEnumerable<int> ` 不是 `IEnumerable<object> `?<div id="text_translate"><p> IEnumerable<T>接口是协变的,因此IEnumerable<string>是IEnumerable<object> 。 但是为什么IEnumerable<int><em><strong>不是</strong></em>IEnumerable<object>而int是object ?</p></div></object></int> - Why `IEnumerable<int>` is not `IEnumerable<object>`? MvvmCross绑定ObservableCollection <MyItem> 到ObservableCollection <object> - MvvmCross binding ObservableCollection<MyItem> to ObservableCollection<object> 绑定到ObservableCollection中对象的ObservableCollection属性 - Binding to ObservableCollection property on object within ObservableCollection
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM