Привязка MVVM к событиям CLR - PullRequest
4 голосов
/ 27 июня 2011

Как вы собираетесь связать событие CLR с помощью шаблона mvvm?

Для перенаправленных событий я использую EventToCommandTrigger из фреймворка Cinch, и это прекрасно работает.

Я выписался Поведения и эффекты из примеров Expression Blend, и похоже, что DataEventTrigger - это то, что я должен использовать, но этот пример немного сбивает с толку.

Я хочу, чтобы событие IsVisibleChanged запустило мой IsVisibleChangedCommand,Я также не уверен, какой код должен идти во ViewModel для поддержки этого.

<i:Interaction.Triggers>

    <i:EventTrigger EventName="SelectedItemChanged">
        <framework:EventToCommandTrigger Command="{Binding SelectedMenuItemChangedCommand}"
                                        CommandParameter="{Binding SelectedValue, ElementName=lstClusters}" />
    </i:EventTrigger>

    <framework:DataEventTrigger EventName="IsVisibleChanged"
                            Source="{Binding IsVisibleChangedCommand}">
    </framework:DataEventTrigger>

</i:Interaction.Triggers>

1 Ответ

7 голосов
/ 28 июня 2011

Вы можете использовать Expression Blend SDK для вызова команд в ответ на события в целом, однако мой опыт показывает, что не все события поддерживаются EventTrigger.

Например, это похоже на работу:

<Label Content="LabelText">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseMove">
            <i:InvokeCommandAction Command="{Binding IsVisibleChangedCommand, Mode=OneWay}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Label>

Но это не так:

<Label Content="LabelText">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="IsVisibleChanged">
            <i:InvokeCommandAction Command="{Binding IsVisibleChangedCommand, Mode=OneWay}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Label>

Я не уверен, почему, но Blend SDK, похоже, не нравится свойство IsVisible. Вы можете сделать что-то подобное, но используя Visibility (вместо IsVisible) с PropertyChangedTrigger, например:

<Label x:Name="label1" Content="LabelText">
    <i:Interaction.Triggers>
        <ei:PropertyChangedTrigger Binding="{Binding Visibility, ElementName=label1}">
            <i:InvokeCommandAction Command="{Binding IsVisibleChangedCommand, Mode=OneWay}"/>
        </ei:PropertyChangedTrigger>
    </i:Interaction.Triggers>
</Label>

Кстати - вот пространства имен:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

Кроме того, вот еще одно решение вашей конкретной проблемы, для которого не требуется Blend SDK:

Вместо прямой привязки события к команде, вы можете привязать свойство Visibility вашего объекта к свойству viewmodel и выполнить команду из установщика свойств следующим образом:

Вид:

<UserControl x:Class="SampleApp.Views.EventBindingDemoView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Height="200" Width="200">
    <UserControl.Resources>
        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
    </UserControl.Resources>
    <Grid>
        <Label Content="LabelText" Visibility="{Binding Path=ElementIsVisible, Mode=TwoWay, Converter={StaticResource BooleanToVisibilityConverter}}"/>

        <!-- The rest of your view here -->

    </Grid>
</UserControl>

ViewModel (ViewModelBase должен реализовывать INotifyPropertyChanged и OnPropertyChanged (string propertyName)):

public class EventBindingDemoViewModel : ViewModelBase
{
    private bool ElementIsVisibleField = true; // or false if it should initially be hidden
    public bool ElementIsVisible
    {
        get { return this.ElementIsVisibleField; }
        set
        {
            if (this.ElementIsVisibleField != value)
            {
                this.ElementIsVisibleField = value;
                this.OnPropertyChanged("ElementIsVisible");

                // Execute command
                this.IsVisibleChangedCommand.Execute(null);
            }
        }
    }

    public ICommand IsVisibleChangedCommand;

    // The rest of your viewmodel here
}

В любом случае должен работать.

...