C# WPF:命令参数MultiBinding中的绑定自定义依赖项属性

C# WPF:命令参数MultiBinding中的绑定自定义依赖项属性,c#,wpf,xaml,C#,Wpf,Xaml,我想将字典绑定到按钮的CommandParameter。 这是我的xaml代码: 一些字符串 StringObjectPair类: 公共类StringObjectPair:FrameworkElement { 公共字符串密钥{get;set;} public static readonly dependencProperty ValueProperty=dependencProperty.Register(“Value”、typeof(object)、typeof(StringObjectP

我想将字典绑定到按钮的CommandParameter。 这是我的xaml代码:


一些字符串
StringObjectPair类:

公共类StringObjectPair:FrameworkElement
{
公共字符串密钥{get;set;}
public static readonly dependencProperty ValueProperty=dependencProperty.Register(“Value”、typeof(object)、typeof(StringObjectPair)、newpropertyMetadata(defaultValue:null));
公共对象价值
{
获取{return GetValue(ValueProperty);}
set{SetValue(ValueProperty,value);}
}
}
在MyMultiValueConverter中,将值[1]转换为值[1]。值和值[2]。值属性可以看到null,但User.Id和User.Name不等于null。 在输出窗口中没有错误。 我如何绑定它?

我找到了解决方案

StringObjectPair类中的更改:

公共类StringObjectPair
{
公共字符串密钥{get;set;}
公共对象值{get;set;}
}
XAML中的更改:


一些字符串
在MyMultiValueConverter中,我只是根据一个值获取属性:

var-dataContext=value[0];
var someString=值[1]作为字符串;
var参数=新字典();
对于(变量i=2;icurrent?.GetType().GetProperty(prop)?.GetValue(current,null));
参数.Add(pair.Key,value);
}
}

首先,对于此类场景,使用将逻辑从转换器移动到viewmodel要容易得多。命令的所有输入都应该可以从viewmodel访问。那么您根本不需要命令参数:

public class MainWindowViewModel 
{
    private User _user;
    public MainWindowViewModel()
    {
        MyCommand = new DelegateCommand(() =>
        {
            //Here you can access to User.Id, User.Name or anything from here
        });
    }

    public DelegateCommand MyCommand { get; private set; }

    public User User
    {
        get { return _user; }
        set
        {
            if (value == _user) return;
            _user = value;
            OnPropertyChanged();
        }
    }
}
其次,您与User.Id的原始绑定不起作用,因为您创建的StringObjectPairs不在VisualTree中,因此没有从父级继承的datacontext。但是,为什么不简化多重绑定:

<MultiBinding Converter="{StaticResource MyMultiValueConverter}">
    <Binding Source="SomeString" />
    <Binding Path="User.Id" />
    <Binding Path="User.Name" />
</MultiBinding>
我可以想象在没有多重绑定的情况下使用更简单的解决方案:

<Button Command="..."
        CommandParameter="{Binding User, Converter={StaticResource MyConverter}, 
                                         ConverterParameter=SomeString}" />
编辑: 如果您坚持将键值对传递给命令(虽然我不认为它是一个好的实践),您可以简化XAML,例如:

<MultiBinding Converter="{StaticResource MyMultiValueConverter}">
    <Binding Source="SomeString" ConverterParameter="SomeString" Converter="{StaticResource KeyValueConverter}" />
    <Binding Path="User.Id" ConverterParameter="Id" Converter="{StaticResource KeyValueConverter}"/>
    <Binding Path="User.Name" ConverterParameter="Name" Converter="{StaticResource KeyValueConverter}"/>
</MultiBinding>

公共类KeyValueConverter:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
返回新的KeyValuePair((字符串)参数,值);
}
}
公共类字典MultiConverter:IMultiValueConverter
{
公共对象转换(对象[]键值,类型targetType,对象参数,CultureInfo区域性)
{
返回keyValues.Cast()
.ToDictionary(i=>i.Key,i=>i.Value);
}
}

此选项不适用于解决方案。目的是通过一本“键值”字典。Ie有一个命令接受字典参数。还有很多按钮,都有不同的参数。
public class MyConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var user = (User)value;

        var someString = (string)paramenter;
        int userId = user.Id;
        string userName = user.Name;

        return ...
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
<MultiBinding Converter="{StaticResource MyMultiValueConverter}">
    <Binding Source="SomeString" ConverterParameter="SomeString" Converter="{StaticResource KeyValueConverter}" />
    <Binding Path="User.Id" ConverterParameter="Id" Converter="{StaticResource KeyValueConverter}"/>
    <Binding Path="User.Name" ConverterParameter="Name" Converter="{StaticResource KeyValueConverter}"/>
</MultiBinding>
public class KeyValueConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return new KeyValuePair<string, object>((string)parameter, value);
    }
}


public class DictionaryMultiConverter : IMultiValueConverter
{
    public object Convert(object[] keyValues, Type targetType, object parameter, CultureInfo culture)
    {
        return keyValues.Cast<KeyValuePair<string, object>>()
                        .ToDictionary(i => i.Key, i => i.Value);
    }
}