I am trying to add an Interaction Trigger to a ButtonTool, but it is not working. I don't get any errors on the Output window when I run my solution, but it doesn't do anything either.
1.- I have a Ribbon Window with a Ribbon and a Dock Manager
2.- I’m trying to use the Interaction triggers on a Button Tool to collapse a Split Pane
<igWpf:ButtonTool Caption="Framework"
x:Name="FrameworkButton"
LargeImage="{DynamicResource Image_PlaceHolder32}"
Style="{DynamicResource StandardHighPriority}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseLeftButtonDown">
<ei:GoToStateAction StateName="FrameworkCollapsed"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</igWpf:ButtonTool>
3. - The Interaction Trigger is calling a Visual State that is presented at the Ribbon Level and the Visual State is targeting the Split Pane (RightPaneProperties) in the Dock Manager
<!-- Visual States -->
<VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="VisualStateGroup"> <VisualState x:Name="FrameworkCollapsed"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="RightPaneProperties"> <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups>
<!--DockManager-->
<igDock:XamDockManager> <igDock:XamDockManager.Panes> <igDock:SplitPane igDock:XamDockManager.InitialLocation="DockedRight" Width="300" x:Name="RightPaneProperties"> <igDock:ContentPane x:Name="bottomEdgeDock1" Header="Framework"> <local:Framework/> </igDock:ContentPane> </igDock:SplitPane> </igDock:XamDockManager.Panes>
Attached you can find the full xaml. Why is the interaction Trigger not working?
Thank you!
Hello Dzyann,
I have taken a look at your xaml file and created a sample project for you. In order to make it work i had to do the following changes:
- Moved the VisualStateManager.VisualStateGroup inside the split pane (RightPaneProperties)
- Since i don't have your custom behaviour i hooked up to the PreviewMouseLeftButtonDown event and called VisualStateManager.GoToElementState(...)
If you still have issues, please send me a sample project with your custom behavior.
Martin,
Thanks for your solution, it works for us. I'm working with Dzyann on this issue and I have it implemented it in our solution, but I keep getting an error saying that "dock" does not exist in the current context. This is from the CS code you provided here.
private void FrameworkButton_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
VisualStateManager.GoToElementState((SplitPane)dock.Panes[0], "FrameworkCollapsed", false);
}
All,
I figured out the issue on the ButtonTool that will requires no code behind. In the original Interaction.Triggers I needed to define a TargetObject for the GoToStateAction. I've attached the sample code of what the Button Tool looks like.
Also, Martins idea of moving the VisualStatesManager code down to the Split Pane level made it work.
Thanks for your help.
BTW you may end up running into some issues with the approach you are taking. For one thing, visual states use animations and an animated values in WPF DPs always take precedence over local values, etc. So for example if you clicked your button to use the VSM to change the visibility of the SplitPane and then tried to later programmatically set the Visibility to Visible it would stay collapsed because the animation is still in effect and that has a higher precedence. That goes for even if the dockmanager tries to change the visibility of the pane which it will as contentpanes within are added/remove/opened/closed and as a layout is loaded.
Another thing that you will likely hit is that since you are changing the Visibility of the SplitPane you may not be affecting the ContentPanes you think. For example if you drag the ContentPane into a floating state, the SplitPane is still docked on the left (its never moved as it may be hosting other panes or placeholders for where a previously docked pane would be) and so it would already be collapsed and the floating ContentPane would remain visible. What's worst is that if the end user toggled the docked state (e.g. double clicked the floating window's caption) then it would disappear because it would be reparented into its previous docked location which in this case was that split pane and since you have animated the visibility of the split pane to collapsed it would remain collapsed. And if the pane was instead dragged to a different docked location that button would have no impact.
If you are ultimately trying to have a button that controls whether the "framework" ContentPane is displayed then you probably want to instead create a ToggleButtonTool and bind the IsChecked property to the Visibility of the ContentPane. In this way the Visibility of the pane can still be changed from code (e.g. if you load a layout file) or via the ui (e.g. clicking the Close button of the pane) and the state of the button will be updated to reflect the current state. Also this would mean that the button would affect the visibility of the pane regardless of where it is positioned.
e.g.
<igRibbon:ToggleButtonTool Caption="Framework" IsChecked="{Binding ElementName=bottomEdgeDock1, Path=Visibility, Converter={StaticResource visToBool}, Mode=TwoWay}" />
This assumes you have a resource for a converter to converter to/from visibility to bool. e.g.
<igRibbon:XamRibbonWindow.Resources> <igWpf:VisibilityToBooleanConverter x:Key="visToBool" xmlns:igWpf="http://schemas.infragistics.com/xaml/wpf" /></igRibbon:XamRibbonWindow.Resources>
This worked perfectly!
You should probably define your own RoutedCommand and have that set the Visibility to Visible. e.g.
public partial class MainWindow : XamRibbonWindow { public static readonly RoutedCommand ShowPane = new RoutedUICommand("Show", "ShowPane", typeof(MainWindow)); static MainWindow() { CommandManager.RegisterClassCommandBinding(typeof(ContentPane), new CommandBinding( ShowPane, (o, e) => { var cp = (ContentPane)o; cp.Visibility = Visibility.Visible; })); }
public partial class MainWindow : XamRibbonWindow { public static readonly RoutedCommand ShowPane = new RoutedUICommand("Show", "ShowPane", typeof(MainWindow));
static MainWindow() { CommandManager.RegisterClassCommandBinding(typeof(ContentPane), new CommandBinding( ShowPane, (o, e) => { var cp = (ContentPane)o; cp.Visibility = Visibility.Visible; })); }
And then use that command. e.g.
<igRibbon:ButtonTool xmlns:local="clr-namespace:RibbonAndDockManager" Caption="Framework" Command="local:MainWindow.ShowPane" CommandTarget="{Binding ElementName=bottomEdgeDock1}" />
Note I just put the xmlns on the element itself to make it simpler to copy/paste the snippet. You'd of course put this higher up (probably on the window) and change it as needed for wherever you define this command.
Andrew,
This worked great! What could I do for a ButtonTool to expose a panel with only one click? This same behavior but not a Toggle Button.
You're right Andrew, because I ran into this issue and changed it to a Toggle Button this morning. I used the Visual States on the checked and unchecked states of the Toggle Button, but I'll try to work this up since it seems like a cleaner solution that will work with undocking and other scenarios.
I appreciate the feedback.