如何在WPF ItemsControl子中设置数据绑定,以便在父数据上下文中使用属性?

时间:2021-01-15 20:11:32

I have a WPF ListView with a collection of RadioButtons. I want to set the GroupName of the child controls to be bound to a property on the parent data context. At the moment I am doing this by duplicating the property in each of the children's data context but that can't be right.

我有一个WPF列表视图,其中包含一系列的radiobutton。我希望将子控件的GroupName设置为与父数据上下文中的属性绑定。目前,我正在通过在每个子数据上下文中复制属性来实现这一点,但这不可能是正确的。

My XAML:

我的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 is a property on the parent View Model. I currently pass this onto the child View Model (where it is also a property) in the child constructor:

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

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

What is the correct way of doing this?

正确的做法是什么?

3 个解决方案

#1


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


0  

You certainly can do that, but if you don't want to have to copy the GroupName to every child Option instance, you could instead do something like the following

您当然可以这样做,但是如果不希望将GroupName复制到每个子选项实例,您可以执行以下操作

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



}

Then you can use a relative binding so you can look up the control tree to find the right datacontext, so you don't have to copy the ParentGroupName to each child Option instance.

然后您可以使用一个相对绑定,以便查找控制树以找到正确的datacontext,这样您就不必将ParentGroupName复制到每个子选项实例。

#3


0  

If you name your window, you can traverse the root DataContext.

如果您给窗口命名,您可以遍历根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>

#1


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


0  

You certainly can do that, but if you don't want to have to copy the GroupName to every child Option instance, you could instead do something like the following

您当然可以这样做,但是如果不希望将GroupName复制到每个子选项实例,您可以执行以下操作

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



}

Then you can use a relative binding so you can look up the control tree to find the right datacontext, so you don't have to copy the ParentGroupName to each child Option instance.

然后您可以使用一个相对绑定,以便查找控制树以找到正确的datacontext,这样您就不必将ParentGroupName复制到每个子选项实例。

#3


0  

If you name your window, you can traverse the root DataContext.

如果您给窗口命名,您可以遍历根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>