1

Let me explain my requirements:

I have a grid containing several check boxes like this:

<Grid>

    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>

    <CheckBox>1</CheckBox>
    <CheckBox
        Grid.Column="1">2</CheckBox>
</Grid>

I know clearly how to use mvvm light EventToCommand to bind to a command (which is defined in my VM or anywhere else). But, as we all know, I have more than 1 check box. So I have to do it like this:

    <CheckBox
        Content="1">
        <i:Interaction.Triggers>
            <i:EventTrigger
                EventName="Checked">
                <ml:EventToCommand
                    Command="{Binding SomeCommand}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </CheckBox>
    <CheckBox
        Grid.Column="1"
        Content="2">
        <i:Interaction.Triggers>
            <i:EventTrigger
                EventName="Checked">
                <ml:EventToCommand
                    Command="{Binding SomeCommand}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </CheckBox>

If I have more check boxes, I have to C+V again and again so as to make each check box have the same EventToCommand behaviors. What's more annoying is that we also have another event named as Unchecked. Usually the callback for both Checked and Uncheck are totally the same. So I have to C+V again & again & again..........

And finally my XAML is long and complicated!

==============================================

I'm thinking of some workaround like this:

I looked into the source code of Checked as well as Unchecked event, and found that both of them were RoutedEvent with mode as Bubble, which means this routed event call bubble up to the grid which contains them. So I wrote my XAML code like this:

<Grid>  
    <i:Interaction.Triggers>
        <i:EventTrigger
            EventName="ToggleButton.Checked">
            <ml:EventToCommand
                Command="{Binding TestCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    ......several check boxes......
</Grid>

But the above codes won't work. Neither Checked nor Unchecked is ATTACHED event.

Then I deleted "ToggleButton.", like this:

        <i:EventTrigger
            EventName="Checked">
            <ml:EventToCommand
                Command="{Binding TestCommand}" />
        </i:EventTrigger>

Still not working! :(

Events should BUBBLE up to the grid, don't they?

So, anyone have some good ideas about this? Thanks!

Jolinpiggy
  • 50
  • 7

2 Answers2

0

You could define an implicit Style for all CheckBoxes in the Grid:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.Resources>
        <Style TargetType="CheckBox">
            <Setter Property="Command" Value="{Binding SomeCommand}" />
        </Style>
    </Grid.Resources>

    <CheckBox>1</CheckBox>
    <CheckBox Grid.Column="1">2</CheckBox>
</Grid>

And instead of handling the Checked and Unchecked events, you could bind to the IsChecked property of each CheckBox to a source property:

<CheckBox IsChecked="{Binding IsFirstChecked}">1</CheckBox>
mm8
  • 163,881
  • 10
  • 57
  • 88
0

Thank you for ur suggestion. It's really handy. I have also found another solution which was post in this site: link In the above post, another solution was mentioned:

using System;
using System.Windows;
using System.Windows.Interactivity;

namespace NaiveMepUi.GuiCommon
{
public class RoutedEventTrigger : EventTriggerBase<DependencyObject>
{
    public RoutedEventTrigger() { }

    public RoutedEvent RoutedEvent { get; set; }

    protected override void OnAttached()
    {
        Behavior behavior = base.AssociatedObject as Behavior;
        FrameworkElement associatedElement =
            base.AssociatedObject as FrameworkElement;

        if (behavior != null)
        {
            associatedElement =
                ((IAttachedObject)behavior).AssociatedObject as FrameworkElement;
        }
        if (associatedElement == null)
        {
            throw new ArgumentException
                ("RoutedEventTrigger.AssociatedObject is not FrameworkElement.");
        }
        if (RoutedEvent != null)
        {
            associatedElement.AddHandler(
                RoutedEvent,
                new RoutedEventHandler(this.OnRoutedEvent));
        }
    }

    /// <summary>
    /// 路由事件被引发,继而引发基类的事件回调;
    /// 但是这一步会丢弃<paramref name="sender"/>。
    /// 如果事件绑定到命令,则命令只能接收到<paramref name="args"/>;
    /// 作为在 ViewModel 中定义的命令,原则上不应该 View 中定义的元素。
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="args"></param>
    void OnRoutedEvent(object sender, RoutedEventArgs args)
    {
        base.OnEvent(args);
    }

    protected override string GetEventName()
    {
        return RoutedEvent.Name;
    }
}
}

Then I can use it in XAML like this:

       <Grid>     
            <i:Interaction.Triggers>
                <guicommon:RoutedEventTrigger
                    RoutedEvent="CheckBox.Checked">
                    <ml:EventToCommand
                        Command="{Binding }" />
                    <!--todo 测试一下这种设计模式是否可行-->
                </guicommon:RoutedEventTrigger>
            </i:Interaction.Triggers>
       </Grid>
Jolinpiggy
  • 50
  • 7