我有一個在XAML中聲明的視圖(請參見下文)。關聯的視圖模型是使用MEF自動創建的。我希望能夠做這樣的事情:從XAML設置ViewModel屬性值
<local:MyControl Owner={x:Static local:Owners.ProjectOwner} />
所需的淨效應是對於一些視圖模型屬性被設置等於Owners.ProjectOwner。
我可以使用hacky代碼隱藏實現所需的結果,但寧願通過綁定或類似的方式來實現。任何人都可以提出一種做法嗎?
UPDATE
我順從地寫行爲。但我並沒有把所有的努力都放在一個具體的案例上,而是將我的解決方案通用化了,我把它列入下面,以防任何人感興趣。這是Blend行爲(System.Windows.Interactivity.dll),但可以很容易地成爲傳統的附加行爲。
using System;
using System.Windows;
using System.Windows.Interactivity;
namespace BlendBehaviors
{
public class SetViewModelPropertyBehavior : Behavior<FrameworkElement>
{
public static readonly DependencyProperty PropertyNameProperty =
DependencyProperty.Register("PropertyName", typeof(string), typeof(SetViewModelPropertyBehavior));
public static readonly DependencyProperty PropertyValueProperty =
DependencyProperty.Register("PropertyValue", typeof(object), typeof(SetViewModelPropertyBehavior));
public SetViewModelPropertyBehavior()
{ }
public string PropertyName
{
get { return (string)GetValue(PropertyNameProperty); }
set { SetValue(PropertyNameProperty, value); }
}
public object PropertyValue
{
get { return GetValue(PropertyValueProperty); }
set { SetValue(PropertyValueProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
var ao = AssociatedObject;
SetViewModel(ao.DataContext);
ao.DataContextChanged += FrameworkElement_DataContextChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.DataContextChanged -= FrameworkElement_DataContextChanged;
}
private void FrameworkElement_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
SetViewModel(e.NewValue);
}
private void SetViewModel(object viewModel)
{
SetViewModelProperty(viewModel, PropertyName, PropertyValue);
}
private static void SetViewModelProperty(object viewModel, string propertyName, object propertyValue)
{
if (viewModel == null || propertyName == null) {
return;
}
var info = viewModel.GetType().GetProperty(propertyName);
if (info != null && CanAssignValue(propertyValue, info.PropertyType)) {
info.SetValue(viewModel, propertyValue, null);
}
}
private static bool CanAssignValue(object value, Type targetType)
{
if (value == null) {
return !targetType.IsValueType || Nullable.GetUnderlyingType(targetType) != null;
}
return targetType.IsAssignableFrom(value.GetType());
}
}
}
然後使用它是這樣的:
<local:MyControl>
<i:Interaction.Behaviors>
<bb:SetViewModelPropertyBehavior PropertyName="Owner" PropertyValue="{x:Static local:Owners.ProjectOwner}" />
<bb:SetViewModelPropertyBehavior PropertyName="AnotherProperty" PropertyValue="{StaticResource MyResourceKey}" />
</i:Interaction.Behaviors>
</local:MyControl>
我理解並同意你所說的一切。我不一定要在MyControl上聲明一個名爲「Owner」的DependencyProperty - 示例代碼僅僅是說明性的。我可以編寫一個附加的行爲,但希望在第一個實例中解決這個問題,而不使用對視圖模型的強類型引用。會考慮這個並回到你身邊。 – 2011-06-10 08:52:09
我最終實現了Blend行爲:請參閱我的更新。感謝您的貢獻。 – 2011-06-10 15:35:55