【问题标题】:How can I set my data binding in a WPF ItemsControl child to use a property on the parent data context?如何在 WPF ItemsControl 子项中设置我的数据绑定以使用父数据上下文中的属性?
【发布时间】:2010-07-15 15:01:43
【问题描述】:

我有一个带有 RadioButtons 集合的 WPF ListView。我想将子控件的 GroupName 设置为绑定到父数据上下文上的属性。目前我通过在每个孩子的数据上下文中复制属性来做到这一点,但这是不对的。

我的 XAML:

 <ListView ItemsSource="{Binding OptionItems}" >
     <ListView.ItemTemplate>
         <DataTemplate DataType="{x:Type Logging:FilterOptionsRadioListViewModel}">
            <RadioButton GroupName="{Binding GroupName}" Content="{Binding Option.Value}" Tag="{Binding Option.Key}" IsChecked="{Binding IsChecked}" Command="Logging:FilterOptionsRadioListViewModel.CheckedChangedCommand" />
         </DataTemplate>
     </ListView.ItemTemplate>
 </ListView>

GroupName 是父视图模型上的一个属性。我目前将它传递给子构造函数中的子视图模型(它也是一个属性):

var item = new FilterOptionsRadioListItemViewModel(option, this.GroupName);

这样做的正确方法是什么?

【问题讨论】:

    标签: wpf wpf-controls binding


    【解决方案1】:
     <ListView ItemsSource="{Binding OptionItems}" >
         <ListView.ItemTemplate>
             <DataTemplate DataType="{x:Type Logging:FilterOptionsRadioListViewModel}">
                <RadioButton GroupName="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.GroupName}" Content="{Binding Option.Value}" Tag="{Binding Option.Key}" IsChecked="{Binding IsChecked}" Command="Logging:FilterOptionsRadioListViewModel.CheckedChangedCommand" />
             </DataTemplate>
         </ListView.ItemTemplate>
     </ListView>
    

    【讨论】:

    • 谢谢,约翰。这就是我现在正在做的事情。在我看来,这似乎是一种过于复杂的做事方式,但当然不是一旦你将其分解。现在完美运行。
    【解决方案2】:

    您当然可以这样做,但如果您不想将 GroupName 复制到每个子 Option 实例,您可以改为执行以下操作

    // I'm imagining your viewmodels look something like this
    public class ParentViewModel
    {
        private ObservableCollection<Option> m_OptionItems;
        public ObservableCollection<Option> OptionItems
        {
            get { return m_OptionItems; }
            set { m_OptionItems = value; }
        }
    
        private string m_ParentGroupName;
        public string ParentGroupName
        {
            get { return m_ParentGroupName; }
            set
            {
                m_ParentGroupName = value;
            }
        }
    
    
    }
    
    public class Option
    {
        private string m_Value;
        public string Value
        {
            get { return m_Value; }
            set
            {
                m_Value = value;
            }
        }
    
    
    
    }
    

    然后您可以使用相对绑定,这样您就可以查找控件树以找到正确的数据上下文,因此您不必将 ParentGroupName 复制到每个子 Option 实例。

    【讨论】:

    • 谢谢,viggity,这就是我的视图模型的外观,但它是访问父属性的相对绑定让我很难过。我一直在查看使用 RelativeSource 和 FindAncestor 的示例,但我能找到的所有示例都比这个简单的要求更复杂。我不需要浏览层次结构,它只是我需要找到的直接祖先。难道没有一种简单的方法可以只绑定到 XAML 中的上一步吗?
    • 不幸的是,没有办法更上一层楼,不过真的很好:)
    【解决方案3】:

    如果你命名你的窗口,你可以遍历根DataContext。

    <Window x:Class="MyNamespace.MainWindow"
            Name="Window"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
            Title="MainWindow" Height="500" Width="725">
    
    <ListView ItemsSource="{Binding OptionItems}" >
         <ListView.ItemTemplate>
             <DataTemplate DataType="{x:Type Logging:FilterOptionsRadioListViewModel}">
                <RadioButton GroupName="{Binding ElementName=Window, Path=DataContext.ParentGroupName}" Content="{Binding Option.Value}" Tag="{Binding Option.Key}" IsChecked="{Binding IsChecked}" Command="Logging:FilterOptionsRadioListViewModel.CheckedChangedCommand" />
             </DataTemplate>
         </ListView.ItemTemplate>
     </ListView>
    

    【讨论】:

    • 谢谢,丹尼尔。这是否意味着属性 ParentGroupName 需要对窗口中的控件是唯一的?我现在使用 RelativeSource 绑定来查找父级上的属性,并且运行良好。
    猜你喜欢
    • 2013-01-20
    • 2014-10-21
    • 1970-01-01
    • 2011-09-03
    • 2013-06-15
    • 2011-03-11
    • 2010-11-10
    • 2015-06-11
    • 1970-01-01
    相关资源
    最近更新 更多