【问题标题】:Pass a ObservableCollection<object> to UserControl将 ObservableCollection<object> 传递给 UserControl
【发布时间】:2021-01-16 12:58:59
【问题描述】:

我一直在尝试概括将 ObservableCollection 传递给此处提供的 UserControl 的解决方案:

How to bind collection dependency property in UserControl

我把 UserControl 后面的代码改成:

/// <summary>
/// Interaction logic for myUserControl1.xaml
/// </summary>
public partial class myUserControl1 : UserControl
{
    #region Public Section
    public ObservableCollection<object> UCItems
    {
        get;
        set;
    }

    #endregion
    public myUserControl1()
    {
        InitializeComponent();

        UCItems = new ObservableCollection<object>();
    }

    #region UCItemsSource Property

    public static readonly DependencyProperty UCItemsSourceProperty = 
        DependencyProperty.Register("UCItemsSource", typeof(IEnumerable), typeof(myUserControl1));

    public IEnumerable UCItemsSource
    {
        get { return (IEnumerable)GetValue(UCItemsSourceProperty); }
        set { SetValue(UCItemsSourceProperty, value); }
    }

    #endregion
}

并在 xaml 中将 TexBox 更改为 DataGrid:

<UserControl x:Class="OCasDPdemo.myUserControl1"
         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:OCasDPdemo"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
<Grid>
    <ItemsControl ItemsSource="{Binding Path=UCItemsSource, 
                                    RelativeSource={RelativeSource Mode=FindAncestor,
                                                                   AncestorType={x:Type UserControl}}}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <DataGrid x:Name="myDataGrid" ItemsSource="{Binding Path=UCItemsSource.Person}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

我以与原始示例类似的方式填充集合:

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public ObservableCollection<Person> WindowCollection
    {
        get;
        set;
    }
    public MainWindow()
    {
        InitializeComponent();

        DataContext = this;


        var bob = new Person { FirstName = "Bob", LastName = "Brown", Age = 32.1, ID = 101 };
        var jim = new Person { FirstName = "Jim", LastName = "Green", Age = 21.0, ID = 201 };
        var mel = new Person { FirstName = "Mel", LastName = "Black", Age = 20, ID = 111 };

        WindowCollection = new ObservableCollection<Person>() {bob, jim, mel };
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var sue = new Person { FirstName = "Sue", LastName = "White", Age = 64.7, ID = 101 };
        var ted = new Person { FirstName = "Ted", LastName = "Grey", Age = 18.3, ID = 191 };

        WindowCollection.Add(sue);
        WindowCollection.Add(ted);
    }
}

而 MainWindow xaml 是:

<Grid>
    <StackPanel>
        <local:myUserControl1 UCItemsSource="{Binding Path=WindowCollection}" />
        <Button Content="Refresh" Click="Button_Click" />
    </StackPanel>
</Grid>

我得到的是空行(与人数相同)而不是带有列的网格。此设置适用于原生类型,如长和字符串类型(使用 TextBox)。有人可以让我知道我做错了什么。

【问题讨论】:

  • 控件上的依赖属性基本上没有意义。 itemssource 可以绑定到 viewmodel 的 datacontext 中的属性。
  • 不清楚你真正想要什么。 Person 是如何声明的?为什么您认为将Person 对象绑定到DataGrid.ItemsSource 是有意义的? Person 实际上是项目的来源吗? IE。可枚举、集合等?

标签: wpf collections binding dependencies


【解决方案1】:

我自己没有尝试过,但问题似乎出在您的 myUserControl1 XAML 中。

在根 Grid 内部是一个 ItemsControlItemsSource 绑定到 UCItemsSource。这意味着ItemsControl 将为该集合中的每个元素生成一个ContentPresenter - 在您的情况下,这将是您的Persons 列表。

现在,在每个ContentPresenters 中,将创建一个DataTemplate 的实例。您的DataTemplate 包含DataGrid。这意味着您将获得一个完整的 DataGrid 每个 Person

如果您尝试使用一个DataGrid,每个Person 有一行,您可能想要这样的东西:

<UserControl x:Class="OCasDPdemo.myUserControl1"
         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:OCasDPdemo"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <DataGrid x:Name="myDataGrid" ItemsSource="{Binding Path=UCItemsSource, 
                                                        RelativeSource={RelativeSource Mode=FindAncestor,
                                                                                       AncestorType={x:Type UserControl}}}">
            
        </DataGrid>
    </Grid>
</UserControl>

【讨论】:

  • 完美!它现在按预期工作。非常感谢。为了澄清其他人的利益,我试图通过在代码中进行绑定来为任何类与 ObservableCollection 一起工作的用户控件原型。 Keith Stein 的解决方案让我更近了一步。 Keith,你能帮我用代码编写绑定吗?
  • @I.Konuk MainWindow 中的绑定有什么问题?
  • 我认为它会提供更大的灵活性,因为我可以为对象类型使用变量。但是,再想一想,在大多数情况下,MainWindow 容器将在 xaml 中定义。所以没有意义。再次非常感谢您的及时帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-20
  • 2023-03-21
  • 1970-01-01
相关资源
最近更新 更多