wpf中的路由隧道事件

时间:2014-05-06 07:41:02

标签: c# wpf events user-controls routed-events

我在这里向wpf社区提出了一个问题。 我有点无法理解路由隧道事件。在我的应用程序中,我有一个包含工具栏的窗口。 窗口还包含用户控件。工具栏中有一些控件,如视图,用于隐藏/取消隐藏用户控件(视图),就像在Visual Studio中一样。

我在Windows控件中有自定义路由隧道事件。当在工具栏上单击按钮时,我会引发自定义事件(隐藏/取消隐藏)。当点击按钮时,我需要在子用户控件(其名称为" Expander 1")中隐藏扩展器。

有人可以告诉我如何在子用户控件中捕获引发的事件?

感谢。

代码窗口:

public partial class MainWindow : Window
    {
        private static readonly RoutedEvent HideShowMitigationEvent;

        static MainWindow()
            {
            HideShowMitigationEvent = EventManager.RegisterRoutedEvent("HideShowMitigation",
                RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(MainWindow));
            }

        public MainWindow()
            {
            InitializeComponent();
            }

        // The Standard .Net optional event wrapper
        // This is required if we want to register the event handler in XAML       
        public event RoutedEventHandler HideShowMitigation
            {
            add { AddHandler(HideShowMitigationEvent, value); }
            remove { RemoveHandler(HideShowMitigationEvent, value); }
            }

        // Raise the event. overidden from UIElement       
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
            {
           // RaiseEvent(new RoutedEventArgs(HideShowMitigationEvent, this));
            }


        public static ExploredRisks _rootName { get; set; }

        public MainWindow(GeneralTree<string> rawTreeData, Excel.Worksheet sheet,Excel.Workbook Wb)
        {

            //prepares the visual tree for other views
            PrepareVisualTree visualTree = new PrepareVisualTree(rawTreeData, sheet);
            _rootName = visualTree.getVisualTree();
            var l_vm = new MainViewModel();
            l_vm.Load(_rootName);
           TreeListViewMultiColumned view = new TreeListViewMultiColumned( RiskViewModel.CreateTestModel(visualTree.getVisualTree()),sheet,Wb);


            base.DataContext = l_vm;
            InitializeComponent();

        }

        private void UIPanel_Loaded(object sender, RoutedEventArgs e)
        {

        }


        private void RibbonCheckBox_Checked(object sender, RoutedEventArgs e)
        {

           RaiseEvent(new RoutedEventArgs(HideShowMitigationEvent, this));
        }

        private void SimpleClickEventHandlingCode(object sender, RoutedEventArgs e)
            {
            //Expander exp = ((MainWindow)(e.OriginalSource)).RiskProperties.MitigationArea; 
                RoutedEventArgs args = new RoutedEventArgs();
                args.RoutedEvent = HideShowMitigationEvent;
                 RaiseEvent(args);
            }
    }
}

Window Xaml:

<Window>


       <Ribbon x:Name="RibbonWin"  SelectedIndex="0">
             <RibbonTab Header="Views" KeyTip="H">
                <!-- Home  group-->
                <RibbonGroup x:Name="ViewsGroup" Header="Views">
                    <RibbonCheckBox Label="Mitigation" IsChecked="{Binding IsChecked, Mode=TwoWay}" Checked="RibbonCheckBox_Checked" PreviewMouseDown="SimpleClickEventHandlingCode"/>
                    <RibbonCheckBox Label="Properties" IsChecked="{Binding IsChecked, Mode=TwoWay}" Checked="RibbonCheckBox_Checked" />
                </RibbonGroup>
            </RibbonTab>
        </Ribbon>
  <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <UI:TreeListViewMultiColumned x:Name="RiskProperties"  Grid.Column="0"  />
        </Grid>
</Window>

1 个答案:

答案 0 :(得分:0)

我认为在建议解决方案之前,我必须澄清WPF路由事件:

在WPF中,有一个新的路由事件概念。路由事件是沿逻辑树传递的事件。

实施例: 让我们看一下当您单击UI上的按钮时会发生什么。 首先,您将获得MainWindow上发生的PreviewLeftMouseButtonDown事件,然后将元素树从父级传递到子级,直到它到达已单击的按钮。 - &GT;此过程(从父级到子级)称为隧道

其次,您将获得一个在按钮上发生的LeftMouseButtonDown事件,并在元素树中向上传递,直到它到达MainWindow。 - &GT;这个过程(从孩子到父母)被称为冒泡

据我了解,您想要点击按钮打开扩展器。 恕我直言,使用路由事件是不合适的方法。

我认为你可以用一点XAML来解决你的用例。以下是我的建议:

  • 您在工具栏中使用ToggleButton(这可确保用户可以 看到按钮的状态,例如按下或未按下。)
  • 使用DataBinding将ToggleButtons IsChecked属性绑定到 Expanders IsExpanded property。

检查以下(高度简化的)样本:

<Grid>
  <StackPanel>
     <ToggleButton x:Name="openExpanderBtn" Width="100" Height="30" Margin="20" Content="Click to Open" />
     <Expander Width="150" Height="200" IsExpanded="{Binding ElementName=openExpanderBtn, Path=IsChecked}" >
        <Expander.Header>
           This is my Header
        </Expander.Header>
        This is my Body
     </Expander>
  </StackPanel>

备注:我刚想到这只有在UserControl受您控制的情况下才有效。如果是这种情况:很好,否则我将描述另一种解决方案。 Rgds MM