0
votes

I have got a question to wpf community here. I am kind of not able to understand Routing Tunnel Events. In my application, I have got a window which contains a tool bar. Window also contains usercontrols. There are some controls in Tool bar like view which are used to Hide / unhide usercontrols (Views) like in Visual Studio.

I have custom routed tunnel event in windows control. I raise custom event when a button is clicked on toolbar (hide / unhide). I need to hide a expander in child usercontrol (which has a name like "Expander 1") when button is clicked.

Can some one tell me how can I capture the raised event in the child user control?

Thanks.

Code window :

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

1 Answers

0
votes

I think I have to to clarify on WPF Routed Events before I suggest a solution:

In WPF there is a new concept of Routed Events. Routed Events are Events that are passed along the logical tree.

Example: Lets look at what happens when you click a button on your UI. First, you will get a PreviewLeftMouseButtonDown event that occurs on the MainWindow and is then passed down the element tree from parent to child until it reaches the button that has been clicked. -> This process (from parent to child) is called Tunneling

Second, you will get a LeftMouseButtonDown event that occurs on the button and is passed up the element tree until it reaches the MainWindow. -> This process (from child to parent) is called Bubbling

As far as I understand you want to open the expander on the click of the button. IMHO using routed events for this is not the appropriate approach.

I think you can solve your use case with a little XAML. Here is what I suggest:

  • You use a ToggleButton in the Toolbar (this ensures that the user can see the state of the button, e.g. pressed or not pressed.)
  • You use DataBinding to bind the ToggleButtons IsChecked Property to the Expanders IsExpanded property.

Check the following (highly simplified) sample:

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

Remark: It just came to my mind that this only works if the UserControl is under your control. If this is the case: fine, else I will describe another solution. Rgds MM