我正在使用隐式数据模板,它们应用于ItemsControl的项目:
<ItemsControl ItemsSource="{Binding Path=CategoryAttributeVMs}"/>
<DataTemplate DataType="{x:Type my:CategoryAttributeDateFieldVM}">
<DockPanel>
<.....>
<Button Command="{Binding Path=MainViewModel.CopyToChildrenCommand,
Source={StaticResource Locator}}"
CommandParameter="{Binding Mode=OneWay}">
</DockPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type my:CategoryAttributeIntegerFieldVM}">
<DockPanel>
<.....>
<Button Command="{Binding Path=MainViewModel.CopyToChildrenCommand,
Source={StaticResource Locator}}"
CommandParameter="{Binding Mode=OneWay}">
</DockPanel>
</DataTemplate>
这与我的ViewModel数据绑定如下:
public abstract class CategoryAttributeVM
{
protected CategoryAttributeVM(ICategoryAttribute categoryAttribute)
{
_categoryAttribute = categoryAttribute;
}
private readonly ICategoryAttribute _categoryAttribute;
public string Name { get { return _categoryAttribute.Name; } }
public object Value { get { return _categoryAttribute.Value; } }
}
public abstract class CategoryAttributeVM<T> : CategoryAttributeVM
{
protected CategoryAttributeVM(ICategoryAttribute<T> categoryAttribute)
: base(categoryAttribute) { _categoryAttribute = categoryAttribute; }
private readonly ICategoryAttribute<T> _categoryAttribute;
public new T Value
{
get { return _categoryAttribute.Value; }
set { _categoryAttribute.Value = value; }
}
}
public class CategoryAttributeDateFieldVM : CategoryAttributeVM<DateTime?>
{
public CategoryAttributeDateFieldVM(ICategoryAttributeDateField categoryAttributeDateField)
: base(categoryAttributeDateField) { }
}
public class CategoryAttributeIntegerFieldVM: CategoryAttributeVM<Int32?>
{
public CategoryAttributeIntegerFieldVM(ICategoryAttributeIntegerField categoryAttributeIntegerField)
: base(categoryAttributeIntegerField) { }
}
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
CategoryAttributeVMs = new List<CategoryAttributeVM>( new CategoryAttributeVM[]
{
new CategoryAttributeDateFieldVM(new CategoryAttributeDateField("DateField", DateTime.Now)),
new CategoryAttributeIntegerFieldVM(new CategoryAttributeIntegerField("IntField", 123))
});
CategoryAttributeVM2s = new List<CategoryAttributeVM>(new CategoryAttributeVM[]
{
new CategoryAttributeDateFieldVM(new CategoryAttributeDateField("DateField", null)),
new CategoryAttributeIntegerFieldVM(new CategoryAttributeIntegerField("IntField", null))
});
CopyToChildrenCommand = new RelayCommand<CategoryAttributeVM>(DoCopyToChildrenCommand);
}
public IEnumerable<CategoryAttributeVM> CategoryAttributeVMs { get; private set; }
private IEnumerable<CategoryAttributeVM> CategoryAttributeVM2s { get; private set; }
// This an MVVM Light RelayCommand
public RelayCommand<CategoryAttributeVM> CopyToChildrenCommand { get; private set; }
private void DoCopyToChildrenCommand(CategoryAttributeVM ca)
{
foreach (var item in CategoryAttributeVM2s)
{
// How to copy the ca.Value to item.Value where ca and item are of the same type?
if (item.GetType() == ca.GetType())
item.Value = ca.Value; // !! No worky because item.Value refers to the CategoryAttributeVM.Value, which is a readonly Object property
}
}
}
如何从CategoryAttributeVM2s中获取与“ca”类型匹配的对象? 我想我错过了一些基本的东西,但看不到它。
泛型方法会很好但是AFAIK RelayCommand不能以这种方式变得通用:
// This would be great
private void DoCopyToChildrenCommand<T, U>(T ca) where T : CategoryAttributeVM<U>
{
foreach (var item in CategoryAttributeVM2s.OfType<T>())
item.Value = ca.Value; // item.Value is type U, which is perfect
}
// But this can't be, obviously
public RelayCommand<CategoryAttributeVM<U>> CopyToChildrenCommand<U> { get; private set; }
有什么想法吗?
答案 0 :(得分:0)
我不是100%确定我理解您的问题,但为什么不在object
中使用RelayCommand
并且只有在对象可以转换为CanExecute()
时才使ICommand MyCommand { get; set; }
MyCommand = new RelayCommand<object>(
param => DoCopyToChildrenCommand<T, U>(param as T),
param => param is T);
方法返回true您的通用类型?
{{1}}
答案 1 :(得分:0)
最后,我在CategoryAttributeVM
和CategoryAttributeVM<T>
上添加了抽象方法的重载:
public abstract class CategoryAttributeVM
{
<...>
public abstract void UpdateValueFrom(CategoryAttributeVM sourceCategoryAttributeVM);
}
public abstract class CategoryAttributeVM<T> : CategoryAttributeVM
{
<...>
public override void UpdateValueFrom(CategoryAttributeVM sourceCategoryAttributeVM)
{
if (GetType() == sourceCategoryAttributeVM.GetType())
Value = (T)sourceCategoryAttributeVM.Value;
}
}
然后我可以在DoCopyToChildrenCommand中使用它:
private void DoCopyToChildrenCommand(CategoryAttributeVM ca)
{
foreach (var attribute in CategoryAttributeVM2s)
attribute.UpdateValueFrom(ca);
}