【问题标题】:Routed Tunnel Events in wpfwpf中的路由隧道事件
【发布时间】:2014-06-22 17:10:18
【问题描述】:

我有一个关于 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);
            }
    }
}

窗口 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>

【问题讨论】:

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


    【解决方案1】:

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

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

    示例: 让我们看看当您单击 UI 上的按钮时会发生什么。 首先,您将获得一个在 MainWindow 上发生的 PreviewLeftMouseButtonDown 事件,然后将元素树从父级传递到子级,直到它到达已单击的按钮。 -> 这个过程(从父到子)称为Tunneling

    其次,您将获得一个 LeftMouseButtonDown 事件,该事件发生在按钮上,并向上传递到元素树,直到到达 MainWindow。 -> 这个过程(从子到父)称为冒泡

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

    我认为您可以使用一点 XAML 来解决您的用例。这是我的建议:

    • 您在工具栏中使用了一个切换按钮(这样可以确保用户可以 查看按钮的状态,例如按下或不按下。)
    • 您使用 DataBinding 将 ToggleButtons IsChecked 属性绑定到 Expanders IsExpanded 属性。

    检查以下(高度简化的)示例:

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

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

    【讨论】:

    • 谢谢,但它不像你解释的那样工作。我试过了。虽然 isChecked 设置为 true,但绑定不会相应地将扩展器可见性设置为 true 或 false。
    • 代码肯定有问题。如果您发布您当前的代码,我会看看它。
    猜你喜欢
    • 2015-05-11
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    相关资源
    最近更新 更多