使用相同事件的用户控件

UserControls using the same events

我正在制作 Windows 10 个 UWP 应用。 为简单起见,假设我的页面某处有一个 TextBox。在这个 TextBox 下有我的 3 个(不同类型)自定义控件。这 3 个控件具有相同的 属性 和如果用户单击其中一个控件内的按钮会引发的事件,并且订阅此事件的方法会导致 TextBox[ 中的文本=31=] 被分配给控件中的 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;
}

而且我必须对所有控件都这样做,但我可能有很多控件,因为它们是根据需要以编程方式创建的,所以我希望有一些更好的方法来实现它。我想到的一切似乎都是愚蠢的或超级低效的。

提前致谢!

是的,你可以!
它叫做 EventSetter,你可以这样使用它:

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

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

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

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

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 中的基数 class,而不是

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


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