Domanda

I have like 10 buttons on the view, which, when clicked should set adequate property on ViewModel to null (ViewModel is DataContext for View). Think of it like a reset action.

Currently what i have is an ICommand in ViewModel, that each button"s Command is bound to, and then I set a CommandParameter to some value, which will allow me to distinguish what property on ViewModel needs to be updated.

In order to avoid bunch of Ifs, I am thinking of doing something like this (incorrect syntax):

<Button ...>
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
      <Setter Property="PropertyA" Source="DataContext-ViewModel" Value="x:null" />
    </i:EventTrigger>
  <i:Interaction.Triggers>
</Button>

Is this possible to achieve, and how?

È stato utile?

Soluzione

If using Reflection an option for you, then you could use Reflection to set properties in the ViewModel.

Your command execute method will become something like this:

this.GetType().GetProperty((string)CommandParameter).SetValue(this, null, new object[] {});

However, if you prefer the XAML route you mentioned in your question, then you could create a TriggerAction and use that in the EventTrigger. Below is what I tried:

public sealed class SetProperty : TriggerAction<FrameworkElement>
{
    public static readonly DependencyProperty SourceProperty =
        DependencyProperty.Register("Source", typeof (object), typeof (SetProperty), new PropertyMetadata(default(object)));

    /// <summary>
    /// Source is DataContext
    /// </summary>
    public object Source
    {
        get { return (object) GetValue(SourceProperty); }
        set { SetValue(SourceProperty, value); }
    }

    public static readonly DependencyProperty PropertyNameProperty =
        DependencyProperty.Register("PropertyName", typeof (string), typeof (SetProperty), new PropertyMetadata(default(string)));

    /// <summary>
    /// Name of the Property
    /// </summary>
    public string PropertyName
    {
        get { return (string) GetValue(PropertyNameProperty); }
        set { SetValue(PropertyNameProperty, value); }
    }

    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof (object), typeof (SetProperty), new PropertyMetadata(default(object)));

    /// <summary>
    /// Value to Set
    /// </summary>
    public object Value
    {
        get { return (object) GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    protected override void Invoke(object parameter)
    {
        if (Source == null) return;
        if (string.IsNullOrEmpty(PropertyName)) return;

        Source.GetType().GetProperty(PropertyName).SetValue(Source, Value, new object[] {});
    }
}

and XAML:

<Button Content="Reset">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <local:SetProperty Source="{Binding}" PropertyName="PropertyToSet" Value="{x:Null}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

If you do not like Reflection at all, then you could have a Dictionary of Actions in your Viewmodel:

_propertyResetters = new Dictionary<string, Action>
{
    {"PropertyToSet", () => PropertyToSet = null}
};

And, in your Command Execute method you can invoke these actions by doing _propertyResetters[(string)CommandParameter]();

Hope this helps or gives you some ideas.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top