Setting ViewModel property value from XAML

I have a view that is declared in XAML (see below). A linked view model is created automatically using MEF. I want to be able to do something like this:

<local:MyControl Owner={x:Static local:Owners.ProjectOwner} /> 

The desired network effect is a property of some property of the view model, equal to Owners.ProjectOwner.

I can achieve the desired result using the hacker code, but rather I will do it with the help of bindings or in some other way. Can anyone suggest a way to do this?

UPDATE

I put up with what I wrote about behavior. But instead of making every effort exclusively to one specific case, I summarized my decision, and I included it below, if someone is interested. This is the behavior of Blend (System.Windows.Interactivity.dll), but it can just as easily be the usual attached behavior.

 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()); } } } 

Then use it as follows:

 <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> 
+4
source share
1 answer

The goal of any WPF binding should be DependencyProperty . The source can be DependencyProperty , a CLR object that implements INotifyPropertyChanged , or just some object. The target and source objects can be swapped by changing the Binding.Mode property.

But in this case, one of the elements in your binding is a statically resolved property ( Owners.ProjectOwner ). Therefore, this is not a DependencyProperty . Therefore, it can only be displayed as a source. Therefore, what you are binding to (target) should be DependencyProperty . Therefore, it cannot be a property in your view model (unless you created model models based on DependencyObject , which will be an error ).

Thus, you cannot directly bind a property on your virtual machine to a static property. You can write an attached behavior that does this for you, though.

+3
source

All Articles