2011-03-29 127 views
4

我创建了UserControl,它由​​组成。此集合中的每件商品均由ListBox组成。WPF:如何为自定义用户控件创建事件?

我的申请表示为Window,其中包含UserControl。我希望能够管理与ListBox中的物品相关的活动。我怎样才能做到这一点? (我不知道这是否是相关与否,但UserControl是一个从应用程序组件不同。)

这里是UserControl的代码:

<UserControl 
    x:Class="UserControls.CalendarMonthViewControl.CalendarMonthView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    mc:Ignorable="d" 
    d:DesignWidth="580" 
    d:DesignHeight="300" 
    xmlns:calendarMonthViewControl="clr-namespace:UserControls.CalendarMonthViewControl" 
    Name="CalendarMonthViewControl"> 
    <Grid> 
    <ItemsControl 
     ItemsSource="{Binding ElementName=CalendarMonthViewControl, Path=Days}"> 
     <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <UniformGrid Rows="6" Columns="7" /> 
     </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemTemplate> 
     <DataTemplate DataType="{x:Type calendarMonthViewControl:Day}"> 
      <Border> 
      <Grid> 
       <ListBox ItemsSource="{Binding Path=CalendarDayItems}" /> 
      </Grid> 
      </Border> 
     </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
    </Grid> 
</UserControl> 
+0

你想在哪里处理ListBox事件?在窗口中,用户控件还是其他地方?有人必须“处理”事件。 – 2011-03-29 13:39:24

+0

我想在'Window'的代码后面处理事件。 – Boris 2011-03-29 13:41:59

回答

2

@vlad走上正轨。

这里有几个选项。他们都涉及处理路由事件。

要处理路由事件,请使用拥有类的名称,后跟事件的名称。

第一种选择是简单地处理该选择的Window类改变事件(或一些其它ListBox事件):

<Window ... 
     ListBox.SelectionChanged="OnChildListboxSelectionChanged"> 
    ... 
</Window> 

第二个选项(更典型的方法)是处理内的ListBox事件用户控件,然后以某种方式聚合它们并在该级别激发事件。此事件由Window处理。此事件可能是路由事件或标准.NET事件。

<UserControl ... 
      ListBox.SelectionChanged="OnChildListBoxSelectionChanged"> 
    ... 
</UserControl> 

后面的代码在用户控制:

public event EventHandler<MyArgTypeEventArgs> ListBoxUpdated; 

private void OnChildListBoxSelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    // aggregate data and info 
    MyArgTypeEventArgs handler = ListBoxUpdated; 
    if (handler != null) 
     handler.Invoke(this, GenerateArgs()); 
} 

Window处理此事件:

<Window ... 
     ListBoxUpdated="OnListBoxUpdated"> 
    ... 
</Window> 

这应该给你的东西开始。

+0

请注意,如果你愿意,你可以使用类似的方法使用MVVM。视图必须在事件发生时通知视图模型,然后视图模型将聚合并传播事件。 – 2011-03-29 13:56:55

+0

MVVM在使用ItemsControls或ListBoxes中的DataTemplates时效果最佳。如果没有在控件中使用视图模型,可能很难在ItemsControl中使用与单个项目相关联的逻辑。 – 2011-03-29 13:59:07

+0

非常感谢。我决定给MVVM一个镜头(我之前从未使用过我的编码)。 – Boris 2011-03-29 20:50:46

1

我没有使用过他们多少我自己,但我认为RoutedEvents会解决你的问题。事件从您的ListBox冒泡到Window(或树中较低的另一元素),您可以在其中处理它们。

编辑:从引用链接:要使用XAML事件添加处理程序,需要声明的事件名称,因为这是一个事件侦听器的元素的属性。该属性的值是您实现的处理程序方法的名称,该名称必须存在于代码隐藏文件的部分类中。从UIElement

因为UserControl继承,我猜是这样会工作(未经测试ATM):

<UserControl 
    x:Class="UserControls.CalendarMonthViewControl.CalendarMonthView" 
    [...] 
    ListBox.NameOfEvent="EventHandlerName"> 
+0

@Boris增加了细节。 @JoshG为事件处理程序提供了一些不错的代码, – vlad 2011-03-29 14:05:12

+0

感谢您的帮助!我很感激。 – Boris 2011-03-29 20:52:18

0

我不认为你想做什么是正确的做法,因为它的创建您的视图之间不必要的依赖,意味着您的UserControl没有正确封装。

在我看来,最好的解决方案是处理UserControl的viewmodel中的事件,并根据需要在您的Window的viewmodel之间建立关系,以便视图本身是独立的。

+0

感谢您的回复。好的,比方说,我在'UserControl'中调用一个事件。用户控件的代码隐藏将包含事件处理程序。我如何从包含'UserControl'的'Window'代码隐藏内部到达该方法?或者,如果我再次想到错误,请你帮我理解应该怎么做?谢谢一堆。 – Boris 2011-03-29 13:53:04

+0

可以用中介完成。这一切都取决于你的作品如何耦合。如果您使用的是MVVM,它将取决于您的视图模型如何耦合。 – 2011-03-29 13:55:11

+0

@Boris,因为Josh说你需要粘贴这些视图的东西,通过它没有使用MVVM的声音,我会给它一个阅读并削减代码背后的代码,它会在以后偿还一个更清洁的架构,视图和您的业务逻辑很好地分离! – dain 2011-03-29 14:06:24