UserControls使用相同的事件

时间:2017-05-19 07:25:33

标签: c# xaml uwp windows-10-universal

我正在制作Windows 10 UWP应用。 为简单起见,我们说我的页面上有一个 TextBox 。在这个 TextBox 下有我的3种(不同类型)自定义控件。如果用户单击其中一个控件内的按钮,则这3个控件具有相同的属性和事件,订阅此事件的方法会导致 TextBox 中的文本被分配给控件中的 SomeProperty

是否有某种方式可以订阅这些活动,因此我不必使用3种不同的方法处理它,而它们确实在做同样的事情,但是对于3种不同的控件。

这是所有控件共有的代码。有MyControlA,MyControlB和MyControlC

public sealed partial class MyControlA : UserControl
{
    public delegate void StartPositionClickedEventHandler(object sender, EventArgs e);
    public event StartPositionClickedEventHandler StartPositionClicked;

    public string SomeProperty
    {
        get { return (string)GetValue(SomePropertyProperty); }
        set { SetValue(SomePropertyProperty, value); }
    }

    private void StartPosition_Click(object sender, RoutedEventArgs e)
    {
        StartPositionClicked?.Invoke(this, EventArgs.Empty);
    }

    // Using a DependencyProperty as the backing store for SomeProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SomePropertyProperty =
        DependencyProperty.Register("SomeProperty", typeof(string), typeof(MyControlA), null);
}

我在控件

的页面中订阅了该事件
_control.StartPositionClicked += new MyControlA.StartPositionClickedEventHandler(SetCurrentStartPositon);

并处理它

private void SetCurrentStartPositon(object sender, EventArgs e)
{
    _control.SomeProperty = DummyTextBox.Text;
}

我必须为所有控件执行此操作,但我可能会有很多这些控件,因为它们是在需要时以编程方式创建的,所以我希望有更好的方法来执行它。我想到的一切似乎都是愚蠢的或超级低效的。

提前谢谢!

2 个答案:

答案 0 :(得分:1)

是的,你可以!
它被称为EventSetter,您可以像这样使用它:

<Style TargetType="{x:Type local:MyControlA}">
    <EventSetter Event="StartPositionClicked" Handler="SomeAction"/>
</Style>  

您需要将此样式放在父控件中,即GridStackPanel,您还需要实现SomeAction方法。
HTH

答案 1 :(得分:1)

由于您的所有控件都具有相同类型的相同属性,因此有两种方法可以实现您的目标:

1:创建一个基类,它将实现它们共有的代码,并使所有控件继承自它:

public abstract class MyControlBase : UserControl
{
    public delegate void StartPositionClickedEventHandler(object sender, EventArgs e);
    public event StartPositionClickedEventHandler StartPositionClicked;

    public string SomeProperty
    {
        get { return (string)GetValue(SomePropertyProperty); }
        set { SetValue(SomePropertyProperty, value); }
    }

    protected void StartPosition_Click(object sender, RoutedEventArgs e)
    {
        StartPositionClicked?.Invoke(this, EventArgs.Empty);
    }

    // Using a DependencyProperty as the backing store for SomeProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SomePropertyProperty =
        DependencyProperty.Register("SomeProperty", typeof(string), typeof(MyControlA), null);
}

public sealed partial class MyControlA : MyControlBase
{
    // Class specific code
}

请注意,您还需要更改XAML中的基类,而不是像

那样
<UserControl>
    <!-- Your XAML code -->
</UserControl>

你必须使用这样的东西,假设xmlns:local指向MyControlBase所在的命名空间:

<local:MyControlBase>
    <!-- Your XAML code -->
</local:MyControlBase>

然后你可以创建一个类似于这个的事件处理程序:

private void SetCurrentStartPositon(object sender, EventArgs e)
{
    // Get the control that invoked this event
    MyControlBase senderControl = (MyControlBase)sender;
    senderControl.SomeProperty  = DummyTextBox.Text;
}


2:为它们创建一个简单的界面,并使所有三个控件都从中继承:

public interface IMyControl
{
    string SomeProperty { get; set; }
}

因此,在您的代码中,您可以将所有控件的事件订阅到一个看起来像这样的方法:

private void SetCurrentStartPositon(object sender, EventArgs e)
{
    // Get the control that invoked this event
    IMyControl senderControl   = (IMyControl)sender;
    senderControl.SomeProperty = DummyTextBox.Text;
}


我建议使用第一个选项,因为它使您的代码更易于阅读,并避免了更改公共代码时可能出现的不一致。