2015-08-28 264 views
0

我想将字典绑定到CommandParameter的按钮。 这是我的XAML代码:WPF:在命令参数中绑定自定义依赖属性MultiBinding

<Button.CommandParameter> 
    <MultiBinding Converter="{StaticResource MyMultiValueConverter}"> 
     <Binding> 
      <Binding.Source> 
       <system:String>SomeString</system:String> 
      </Binding.Source> 
     </Binding> 
     <Binding> 
      <Binding.Source> 
       <models:StringObjectPair Key="UserId" Value="{Binding User.Id, UpdateSourceTrigger=PropertyChanged}" /> 
      </Binding.Source> 
     </Binding> 
     <Binding> 
      <Binding.Source> 
       <models:StringObjectPair Key="UserName" Value="{Binding User.Name, UpdateSourceTrigger=PropertyChanged}" /> 
      </Binding.Source> 
     </Binding> 
    </MultiBinding> 
</Button.CommandParameter> 

StringObjectPair类:

public class StringObjectPair : FrameworkElement 
{ 
    public string Key { get; set; } 

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(StringObjectPair), new PropertyMetadata(defaultValue: null)); 

    public object Value 
    { 
     get { return GetValue(ValueProperty); } 
     set { SetValue(ValueProperty, value); } 
    } 
} 

在MyMultiValueConverter入值[1]。价值和值[2]。价值性质我看到空值,但是User.Id和User.Name不等于空。 在输出窗口中没有错误。 我该如何绑定这个?

回答

0

首先,对于这种情况,使用将转换器的逻辑移到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:

<MultiBinding Converter="{StaticResource MyMultiValueConverter}"> 
    <Binding Source="SomeString" /> 
    <Binding Path="User.Id" /> 
    <Binding Path="User.Name" /> 
</MultiBinding> 
var someString = (string)values[0]; 
var userId = (int)(values[1] ?? 0); 
var userName = (string)values[2]; 

我可以用想象的更简单solutution没有multibinding:

<Button Command="..." 
     CommandParameter="{Binding User, Converter={StaticResource MyConverter}, 
             ConverterParameter=SomeString}" /> 
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(); 
    } 
} 

编辑: 如果您坚持传递关键值对命令(虽然我不认为这是一个很好的做法),可以简化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> 
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); 
    } 
} 
+0

此选项是不适合的解决方案。目标是通过一个“键值”字典。即有一个命令需要字典参数。并且有很多按钮,都有不同的参数。 – adeptus

0

我找到了解决办法

在StringObjectPair类的变化:

public class StringObjectPair 
{ 
    public string Key { get; set; } 

    public object Value { get; set; } 
} 

变化XAML:

<Button.CommandParameter> 
    <MultiBinding Converter="{StaticResource MyMultiValueConverter}"> 
     <Binding /><!--This is DataContext--> 
     <Binding> 
      <Binding.Source> 
       <system:String>SomeString</system:String> 
      </Binding.Source> 
     </Binding> 
     <Binding> 
      <Binding.Source> 
       <!--Just string in Value--> 
       <models:StringObjectPair Key="UserId" Value="User.Id" /> 
      </Binding.Source> 
     </Binding> 
     <Binding> 
      <Binding.Source> 
       <models:StringObjectPair Key="UserName" Value="User.Name" /> 
      </Binding.Source> 
     </Binding> 
    </MultiBinding> 
</Button.CommandParameter> 

而在MyMultiValueConverter我只是得到一个价值的基础上的属性:

var dataContext = values[0]; 
var someString = values[1] as string; 
var parameters = new Dictionary<string, object>(); 
for (var i = 2; i < values.Length; i++) 
{ 
    var pair = values[i] as StringObjectPair; 
    if (!string.IsNullOrEmpty(pair?.Key) && !parameters.ContainsKey(pair.Key)) 
    { 
     var props = (pair.Value as string)?.Split('.') ?? Enumerable.Empty<string>(); 
     var value = props.Aggregate(dataContext, (current, prop) => current?.GetType().GetProperty(prop)?.GetValue(current, null)); 
     parameters.Add(pair.Key, value); 
    } 
}