3

我有一个自定义控件,例如:

public sealed class BorderEx : Control
{
    public static readonly RoutedEvent ReloadClickEvent = EventManager.RegisterRoutedEvent("ReloadClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(BorderEx));

    public event RoutedEventHandler ReloadClick
    {
        add { AddHandler(ReloadClickEvent, value); }
        remove { RemoveHandler(ReloadClickEvent, value); }
    }

    void RaiseReloadClickEvent()
    {
        var newEventArgs = new RoutedEventArgs(ReloadClickEvent);
        RaiseEvent(newEventArgs);
    }

    static BorderEx()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(BorderEx), new FrameworkPropertyMetadata(typeof(BorderEx)));
    }
}        

并且在 generic.xaml 上单击 reloadButton 时出现事件

<ControlTemplate TargetType="{x:Type cbr:BorderEx}">

<ControlTemplate.Triggers>

    <Trigger SourceName="reloadButton" Property="IsPressed" Value="True">
        <Setter TargetName="reloadButton" Property="Background" Value="Green"/>
        <EventSetter Event="ReloadClick" Handler="RaiseReloadClickEvent"></EventSetter>
    </Trigger>
</ControlTemplate.Triggers>

</ControlTemplate

但我不知道如何从内部按钮引发这个外部事件。花最后几个小时谷歌搜索,结果一无所获。以上 EventSetter 不工作。

4

2 回答 2

3

这部分还可以

    public static readonly RoutedEvent ReloadClickEvent = EventManager.RegisterRoutedEvent("ReloadClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(BorderEx));

    public event RoutedEventHandler ReloadClick
    {
        add { AddHandler(ReloadClickEvent, value); }
        remove { RemoveHandler(ReloadClickEvent, value); }
    }

    static BorderEx()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(BorderEx), new FrameworkPropertyMetadata(typeof(BorderEx)));
    }

我必须创建依赖属性,所以我可以更改点击事件的一些值

    public static readonly DependencyProperty ReloadProperty = DependencyProperty.Register("Reload", typeof (bool), typeof (BorderEx), new PropertyMetadata(default(bool), ReloadClicked));
    public bool Reload
    {
        get { return (bool) GetValue(ReloadProperty); }
        set { SetValue(ReloadProperty, value); }
    }

我可以通过更改触发的其他方法来处理它

    private static void ReloadClicked(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        if (!((bool) e.NewValue)) return;
        var sender = (BorderEx) o;
        sender.RaiseEvent(new RoutedEventArgs(ReloadClickEvent));
    }

那么它只需要改变点击值

<ControlTemplate.Triggers>
    <Trigger SourceName="reloadButton" Property="IsPressed" Value="True">
        <Setter TargetName="reloadButton" Property="Background" Value="Green"/>
        <Setter Property="Reload" Value="True"/>
    </Trigger>
</ControlTemplate.Triggers>
于 2013-07-31T20:50:09.093 回答
2

您的事件看起来很棒,但事实是EventSetter无法在触发器中设置。引用链接

因为使用 EventSetter 连接事件处理程序是一个通过 IStyleConnector 接口探测的编译时功能,所以 XAML 编译器使用另一个名为 IComponentConnector 的接口来连接独立 XAML 元素的事件处理程序。

你可以这样做。识别EventSetter外部触发器,例如在早期Style/ Template

<Style TargetType="{x:Type local:BorderEx}">
    <EventSetter Event="Button.Click" Handler="ReloadClickEvent" />

...

</Style>

Code behind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }        

    private void ReloadClickEvent(object sender, RoutedEventArgs e)
    {
        RaiseEvent(new DemoEventArgs(BorderEx.ReloadClickEvent, sender));
    }
}

public class DemoEventArgs : RoutedEventArgs
{
    public DemoEventArgs(RoutedEvent routedEvent, object source) : base(routedEvent, source)
    {
        MessageBox.Show("Raise!");
    }
}

public sealed class BorderEx : Control
{
    public static readonly RoutedEvent ReloadClickEvent = EventManager.RegisterRoutedEvent("ReloadClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(BorderEx));

    public event RoutedEventHandler ReloadClick
    {
        add { AddHandler(ReloadClickEvent, value); }
        remove { RemoveHandler(ReloadClickEvent, value); }
    }

    private void RaiseReloadClickEvent()
    {
        var newEventArgs = new RoutedEventArgs(ReloadClickEvent);
        RaiseEvent(newEventArgs);
    }

    static BorderEx()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(BorderEx), new FrameworkPropertyMetadata(typeof(BorderEx)));
    }
}      

或者,使用DependencyProperty(也可以附加)。例子:

属性定义:

public static readonly DependencyProperty SampleProperty =
                                          DependencyProperty.RegisterAttached("Sample",
                                          typeof(bool),
                                          typeof(SampleClass),
                                          new UIPropertyMetadata(false, OnSample));

private static void OnSample(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    if (e.NewValue is bool && ((bool)e.NewValue) == true)
    {
        // do something...
    }
}

在 XAML 中调用。

EventTrigger

<EventTrigger SourceName="MyButton" RoutedEvent="Button.Click">
    <BeginStoryboard>
        <Storyboard>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="MyBox" Storyboard.TargetProperty="(local:SampleClass.Sample)">
                <DiscreteObjectKeyFrame KeyTime="0:0:0">
                    <DiscreteObjectKeyFrame.Value>
                        <sys:Boolean>True</sys:Boolean>
                    </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
    </BeginStoryboard>
</EventTrigger>

DataTrigger(in Style/ DataTemplate/ etc) 一起使用:

<DataTrigger Binding="{Binding ElementName=MyBox, Path=Status), Mode=OneWay}" Value="True">
    <Setter Property="(local:SampleClass.Sample)" Value="True" />
</DataTrigger>

Trigger(in Style) 一起使用:

<Trigger Property="MyCheckBox.IsChecked" Value="True">
    <Setter Property="(local:SampleClass.Sample)" Value="True" />
</Trigger>

使用后面的代码:

private void Clear_Click(object sender, RoutedEventArgs e)
{
    SampleClass.SetSampleClass(MyBox, true);
}
于 2013-07-31T19:14:27.673 回答