如何将外部集合 属性 的命令参数传递给 WPF 中的内部集合

How to Pass CommandParameter of Outer Collection Property to a Inner Collection in WPF

这里是模型 MobileModel 的外部 ObservableCollection。 MobileModel 有一个 inner Collection 的模型 MobileModelInfo

我需要将 OS 的 属性 作为内部集合中的命令参数传递。

C# 源代码是

public class MobileModel : Notify
{
    private string _brand = string.Empty;
    private ObservableCollection<MobileModelInfo> _model = new ObservableCollection<MobileModelInfo>();
    private string _os = string.Empty;

    public string Brand
    {
        get { return _brand; }
        set { _brand = value; OnPropertyChanged(); }
    }
    public ObservableCollection<MobileModelInfo> Model
    {
        get { return _model; }
        set { _model = value; OnPropertyChanged(); }
    }

    public string OS
    {
        get { return _os; }
        set { _os = value; OnPropertyChanged(); }
    }
}

public class MobileModelInfo
{
    public string Name { get; set; }
    public bool IsMobileSelected { get; set; }
}

public void GetMobile()
    {
        List<MobileModel> mList = new List<MobileModel>();
        List<MobileModelInfo> modList = new List<MobileModelInfo>();
        MobileModel mob = new MobileModel();

        modList.Clear();
        mob.Brand = "Apple";
        modList.Add(new MobileModelInfo { Name = "iPhone 4" });
        modList.Add(new MobileModelInfo { Name = "iPhone 5" });
        modList.Add(new MobileModelInfo { Name = "iPhone 6" });
        mob.Model = new ObservableCollection<MobileModelInfo>(modList);
        mob.OS = "IOS";
        mList.Add(mob);

        mob = new MobileModel();
        modList.Clear();
        mob.Brand = "Samsung";
        modList.Add(new MobileModelInfo { Name = "S4" });
        modList.Add(new MobileModelInfo { Name = "S5" });
        modList.Add(new MobileModelInfo { Name = "S6" });
        mob.Model = new ObservableCollection<MobileModelInfo>(modList);
        mob.OS = "Android";
        mList.Add(mob);

        mob = new MobileModel();
        modList.Clear();
        mob.Brand = "MicroSoft";
        modList.Add(new MobileModelInfo { Name = "Lumina 9900" });
        modList.Add(new MobileModelInfo { Name = "Opera X220" });
        mob.Model = new ObservableCollection<MobileModelInfo>(modList);
        mob.OS = "Windows";
        mList.Add(mob);

        mob = new MobileModel();
        modList.Clear();
        mob.Brand = "Sony Ericssion";
        modList.Add(new MobileModelInfo { Name = "S4" });
        modList.Add(new MobileModelInfo { Name = "S5" });
        modList.Add(new MobileModelInfo { Name = "S6" });
        mob.Model = new ObservableCollection<MobileModelInfo>(modList);
        mob.OS = "Android";
        mList.Add(mob);

        MobileList = new ObservableCollection<MobileModel>(mList);
    }

XAML源代码

<ListBox Name="MobieDetail" ItemsSource="{Binding MobileList}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid >
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Name="Brand" Width="200"/>
                        <ColumnDefinition Name="Mobile" Width="90"/>
                        <ColumnDefinition Name="OS" Width="120"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding Brand}" MaxWidth="195" TextWrapping="Wrap"  Grid.Column="0"/>
                <ComboBox Name="MobileName" ItemsSource="{Binding Model,UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Width="220" HorizontalAlignment="Left" VerticalAlignment="Center">
                    <ComboBox.ItemTemplate>
                        <DataTemplate>
                            <CheckBox x:Name="ChkSelect" Content="{Binding Name}" IsChecked="{Binding IsMobileSelected}">
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="Checked">
                                        <commandHelper:EventToCommand Command="{Binding ElementName=MobieDetail, Path=MobieDetailCommand}">
                                            <commandHelper:EventToCommand.CommandParameter>
                                                <MultiBinding>
                                                    <Binding Path="DataContext"></Binding>
                                                    <Binding ></Binding>
                                                </MultiBinding>
                                            </commandHelper:EventToCommand.CommandParameter>
                                        </commandHelper:EventToCommand>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </CheckBox>
                        </DataTemplate>
                    </ComboBox.ItemTemplate>
                    <TextBlock Text="{Binding OS}" MaxWidth="195" TextWrapping="Wrap"  Grid.Column="2"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

如何在 <Binding Path="DataContext"></Binding>

中传递 属性 OS

首先为您的 MultiValueBinding 创建一个转换器,它将两个属性合并为一个 Tuple,它将作为参数传递给您的命令:

 public class CombineTupletConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values==null)            
            return null;
        return new Tuple<object,object>(values[0],values[1]);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

并将其添加到您的资源中:

  <Window.Resources>
    <YourNameSpace:CombineTupletConverter x:Key="CombineTupletConverter"/>
</Window.Resources>

多重绑定时使用该转换器。要获得 Os 属性 和 Selected MobileModelInfo,请使用 RelativeSource 绑定:

 <ComboBox Name="MobileName" ItemsSource="{Binding Model,UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Width="220" HorizontalAlignment="Left" VerticalAlignment="Center">
                        <ComboBox.ItemTemplate>
                            <DataTemplate>
                                <CheckBox x:Name="ChkSelect" Content="{Binding Name}" IsChecked="{Binding IsMobileSelected}">
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="Checked">
                                            <commandHelper:EventToCommand Command="{Binding ElementName=MobieDetail, Path=DataContext.MobieDetailCommand}">
                                                <commandHelper:EventToCommand.CommandParameter>
                                                    <MultiBinding Converter="{StaticResource CombineTupletConverter}">
                                                        <Binding Path="DataContext" RelativeSource="{RelativeSource AncestorType={x:Type CheckBox}}"></Binding>
                                                        <Binding Path="DataContext.OS" RelativeSource="{RelativeSource AncestorType={x:Type ComboBox}}"></Binding>                                                            
                                                    </MultiBinding>
                                                </commandHelper:EventToCommand.CommandParameter>
                                            </commandHelper:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </CheckBox>
                            </DataTemplate>
                        </ComboBox.ItemTemplate>
                    </ComboBox>

您的命令应如下所示:

private RelayCommand<Tuple<object,object>> _mobieDetailCommand;
    public RelayCommand<Tuple<object, object>> MobieDetailCommand
    {
        get
        {
            return _mobieDetailCommand
                ?? (_mobieDetailCommand = new RelayCommand<Tuple<object, object>>(
                (tuple) =>
                {
                    var mobileInfo=tuple.Item1 as MobileModelInfo;
                    var os=tuple.Item2.ToString();                        
                    //Your logic
                }));
        }
    }