将事件从自定义控件传播到表单

时间:2013-07-31 16:12:33

标签: c# wpf events custom-controls

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

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)));
    }
}        

并且reloadButton点击了generic.xaml

时出现了事件
<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不起作用。

2 个答案:

答案 0 :(得分: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)));
    }

我必须创建依赖属性,所以我可以在click事件

上更改一些值
    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>

答案 1 :(得分:2)

您的活动看起来很棒,但无法在触发器中设置EventSetter这一事实。引自link

  

因为使用EventSetter连接事件处理程序是一个编译时功能,它通过IStyleConnector接口检测,所以有另一个名为IComponentConnector的接口,XAML编译器使用该接口为独立的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一起使用(Style / DataTemplate / etc):

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

Trigger一起使用(在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);
}