Call events or methods located in a Class from XAM

2019-03-01 06:11发布

Hi i am trying if it's possible having an Event like TextChanged (of a TextBox) located in another place independent of the Window CodeBehind (like a Class).

What i am trying to do is having in the ResourceDictionary a reference to an event of the TextBox. (Because the ResourcesDictionaries doesn't have a CodeBehind.)

Note: It really have to be by this way, because i am customizing another control to have some TextBoxes dynamically and all the TextBoxes will fire the same event when TextChanged occurs.

2条回答
放荡不羁爱自由
2楼-- · 2019-03-01 06:24

Edit: Disregard this unless you want to subclass TextBox to execute a command on TextChanged. (I think the trigger-method is to be preferred.)

But it's possible making reference in ResourceDictionaries to an Event located in the CodeBehind of the Window where that control belongs? Imagine the following, instead of we are setting an Event to a Control in the XAML, we do that in the dictionary in a style. That is possible?

I would suggest Commands for this; define a RoutedCommand somewhere:

public static class Commands
{
    public static RoutedCommand DoStuff = new RoutedCommand();
}

Set it to the button in the dictionary:

<Button x:Key="TheButton" Content="Click"
        Command="{x:Static local:Commands.DoStuff}" />

And create a command binding:

<Grid>
    <Grid.CommandBindings>
        <CommandBinding Command="{x:Static local:Commands.DoStuff}"
                        Executed="DoStuff_Executed"
                        CanExecute="DoStuff_CanExecute"/>
    </Grid.CommandBindings>
    <StaticResource ResourceKey="TheButton"/>
</Grid>
private void DoStuff_Executed(object sender, ExecutedRoutedEventArgs e)
{
    // What happens if the command is executed, in this case the Button-click can
    // cause this to happen, you can also create KeyBindings which can execute
    // commands for example.
    MessageBox.Show("!");
}
private void DoStuff_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true; //No condition: Command can always be executed

    // e.CanExecute = false causes the button to be disabled.
}
查看更多
我想做一个坏孩纸
3楼-- · 2019-03-01 06:27

I would suggest triggers. You can read more about them here: http://www.silverlightshow.net/items/Behaviors-and-Triggers-in-Silverlight-3.aspx

Essentially you can, in xaml, hook a control's event to a trigger and have it execute a method or command else where.

Edit: I should note that while it does say 'Silverlight' it all applies to WPF as well. Edit2: The MVVM toolkit provides an EventToCommandTrigger that would let you do something like this:

http://blog.galasoft.ch/archive/2009/11/05/mvvm-light-toolkit-v3-alpha-2-eventtocommand-behavior.aspx

Kudos to H.B.'s answer for reminding me about the command way of doing this

Edit3: Better example, this borrows heavily from how the MVVM world would do this. Since the EventToCommand binding would attached to whatever the control's context is, you could stick this in your ResourceDictionary and anywhere you place it, it would attempt to find that TextChangeCommand property.

 <Window x:Class="TestBed.TestWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras">
    <Grid>
        <TextBox x:Name = "MyTextBox">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="TextChanged">
                    <cmd:EventToCommand Command="{Binding TextChanged, Mode=OneWay}"
                                        CommandParameter="{Binding Text, 
                                              ElementName=MyTextBox, Mode=OneWay}"
                        MustToggleIsEnabledValue="True" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TextBox>
    </Grid>
</Window>

and the codebehind:

public partial class TestWindow : Window
{
    public TestWindow()
    {
        this.TextChangedCommand = new RelayCommand<string>(
            (str) => TextChanged(str));

        InitializeComponent();
    }

    public RelayCommand<string> TextChangedCommand
    {
        get;
        private set;
    }

    public void TextChanged(string str)
    {
    }
}
查看更多
登录 后发表回答