【问题标题】:Binding to user control's collection property items in xaml在 xaml 中绑定到用户控件的集合属性项
【发布时间】:2012-09-21 09:57:15
【问题描述】:

我创建了一个带有集合属性的用户控件:

    public static readonly DependencyProperty
    MyListProperty = DependencyProperty.Register(
        "MyList",
        typeof(ObservableCollection<Test>),
        typeof(UserControl1),
        new FrameworkPropertyMetadata(new ObservableCollection<Test>())
        );

    public ObservableCollection<Test> MyList
    {
        get { return (ObservableCollection<Test>)base.GetValue(MyListProperty); }
        set { base.SetValue(MyListProperty, value); }
    }

    public static readonly DependencyProperty
    BProperty = DependencyProperty.Register(
        "B",
        typeof(string),
        typeof(UserControl1),
        new FrameworkPropertyMetadata(null)
    );

    public string B
    {
        get { return (string)base.GetValue(BProperty); }
        set { base.SetValue(BProperty, value); }
    }

测试类是:

public class Test : DependencyObject
{
    public static readonly DependencyProperty
    AProperty = DependencyProperty.Register(
        "A",
        typeof(string),
        typeof(Test),
        new FrameworkPropertyMetadata(null)
    );

    public string A 
    {
        get { return (string)base.GetValue(AProperty); }
        set { base.SetValue(AProperty, value); }
    }
}

然后,我正在尝试使用我的控件进行绑定:

    <TextBox x:Name="tb1" Text="def"/>
    <my:UserControl1 x:Name="uc1" B="{Binding ElementName=tb1, Path=Text}">
        <my:UserControl1.MyList>
            <my:Test A="{Binding ElementName=tb1, Path=Text}"></my:Test>
            <my:Test A="100"></my:Test>
        </my:UserControl1.MyList>
    </my:UserControl1>

第一个绑定(使用用户控件的 B 属性)正常工作。问题在于第二个绑定(具有 Test 的 A 属性,即 MyList 元素)。调试时,我在 MyList 中有两个项目,但第一个的 A 属性为空。请告诉我我在这里缺少什么?

【问题讨论】:

    标签: wpf xaml binding


    【解决方案1】:

    这里的问题是,绑定到 ElementName=tb1 无法解决,即使它永远不会被评估。为 WPF 应用程序的可视树或逻辑树中的 DependencyObject 解析到 ElementName 的绑定。将项目添加到您的 ObservableCollection (MyList) 仅意味着将项目添加到集合中,而不是添加到可视化树中。

    编辑: 这是 cmets 中讨论的方法:

    在您的窗口/页面中:

    <Window.Resources>
        <!-- Declare the ViewModel as Resource -->
        <my:ViewModel x:Key="viewModel">
            <my:ViewModel.MyList>
                <my:Test A="Hello sweet" />
                <my:Test A="ViewModel" />
            </my:ViewModel.MyList>
        </my:ViewModel>
    </Window.Resources>
    
    <!-- Assign Ressource as DataContext -->
    <StackPanel DataContext="{StaticResource viewModel}">
    
        <TextBox x:Name="tb1" Text="def"/>
    
        <!-- Reference your list within the ViewModel -->
        <ListBox ItemsSource="{Binding Path=MyList}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <!-- Bind your property  -->
                    <TextBlock Text="{Binding Path=A}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </StackPanel>
    

    以及ViewModel的实现:

    public class ViewModel
    {
        public ViewModel()
        {
            this.MyList = new ObservableCollection<Test>();
        }
    
        public ObservableCollection<Test> MyList { get; set; }
    }
    

    当然,Test 类不再需要实现 DependencyObject。简单的获取/设置属性就可以了。

    【讨论】:

    • 好的,那么如何让它像在 ListBox 控件中一样工作呢? -> 绑定到 ListBoxItem 可以正常工作。
    • 为您的UserControl1 添加一个ListBox 到您的XAML。将 ListBox 的 ItemsSource 绑定到您的列表 ItemsSource={Binding Path=MyList, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=my:UserControl1}}。将 ItemTemplate 设置为 DataTemplate,其中包含一个 TextBlock,例如,它绑定到 A Text={Binding Path=A}。这应该符合您的预期。
    • 您能否发布一个示例代码,因为我不明白,我不确定您是否理解我的需要。我想用 xaml 中的项目(测试对象)填充 MyList,就像在 ListBox 中完成的那样:
    • 好的,我可以这样做,但实际上我需要更多关于您实际要实现的目标的信息。您想如何使用您的 MyList?对于 WPF 编码,您已经做的事情非常少见。如果我详细了解用例,也许我可以向您展示更好的方法。
    • P.S:您问它如何用于 ListBoxes:ListBox 是一个 ItemsControl。 ListBox 的ItemsContainer 是一个ListBoxItem,一个简单的ContentControl,它包含一个ContentPresenter,通过ItemTemplate 将实际数据可视化。对于添加到 ListBox.Items 集合中的每个项目,都会生成一个容器 (ListBoxItem),然后将数据可视化。也可以直接从 XAML 添加带有内容的 ListBoxItems。在内部,默认情况下,在 ListBox 的模板中,ItemContainers 被添加到 VirtualizingStackPanel,然后它是可视树中的直接父级
    猜你喜欢
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多