[英]WPF: Binding custom dependency property in command parameter MultiBinding
我想将字典绑定到按钮的CommandParameter。 这是我的xaml代码:
<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中,将values [1] .Value和values [2] .Value属性放入空值,但User.Id和User.Name不等于空值。 在输出窗口中没有错误。 我该如何绑定呢?
我找到了解决方案
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);
}
}
首先,对于这种情况,使用逻辑从转换器到视图模型的转换要容易得多。 该命令的所有输入都应该可以从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绑定无效,因为创建的StringObjectPair不在VisualTree中,因此没有从父级继承的datacontext。 但是,为什么不简化多重绑定:
<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];
我可以想象使用更简单的解决方案而无需多重绑定:
<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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.