05-16-2013 02:17 PM
Hi,
Is there a way to attach a mouse click handler to individual items in a WPF Legend control?
I added the event handler to the Legend itself, but the handler only gets called when I click outside of an actual item in the Legend. The toggle buttons themselves don't seem to trigger the callback. What I'm trying to do is hide non-primary axes when their corresponding plot is hidden by clicking on the toggle button in the legend.
For reference, this is what I tried:
<ni:Legend Name="_legend" BorderThickness="0" MouseUp="_legend_MouseUp">
Any help is appreciated.
Solved! Go to Solution.
05-17-2013 10:06 AM
The default data templates used by the legend contain buttons and text boxes that handle mouse events. The easiest way to avoid this is to use the corresponding preview event, such as PreviewMouseUp
. Another option is to create a custom data template without the interactive elements, like this one for plots:
<DataTemplate DataType="{x:Type ni:Plot}">
<TextBlock Text="{Binding Label}" Padding="3" />
</DataTemplate>
05-17-2013 11:55 AM
Thanks for your response. I would like to keep the ability to hide/show plots by clicking on the ToggleButton in the Legend, and the PreviousMouseUp event is firing like I need it to (when a user clicks on the ToggleButton). The problem now is that (I'm guessing since it's a preview) the plots don't hide until after the PreviewMouseUp event handler is finished executing, and there doesn't seem to be a way to correlate the button that was clicked with its associated plot (unless you know of a way to do so).
A possible workaround for this would be to set a timer event in my PreviewMouseUp event handler to show/hide the axes, but this is not a great solution since the time it takes to actually hide the plot may vary depending on the plot size.
It would be ideal to be able to set an OnVisibleChanged event on the Plot object itself, and then just call a method to show/hide axes accordingly. Any suggestions?
05-17-2013 02:11 PM
If I understand your question correctly, you want the axes associated with a plot to have the same visibility as the plot. If that is the case, I would suggest binding the visibility of each axis. To do this for every plot in a graph in code:
IQueryableGraph q = graph;
foreach( var plot in graph.Plots ) {
var binding = new Binding { Source = plot, Path = new PropertyPath( Plot.VisibilityProperty ) };
foreach( var orientation in new[] { Orientation.Horizontal, Orientation.Vertical } ) {
var axis = (Scale)q.GetAxis( plot, orientation ).Value;
BindingOperations.SetBinding( axis, Scale.VisibilityProperty, binding );
}
}
If binding does not fit your scenario and you still need programmatic access to the plot object, then there are other approaches available (e.g. looking up the data context in the visual tree, or registering to be notified for handled events).
05-17-2013 02:26 PM
You understand perfectly. Binding fits my scenario quite well and works in most cases (just tested this approach). The only problem is when there are multiple plots for a single axis; the axis will be bound to only one of the plots and therefore be hidden even if the other plot associated with that axis is still visible. Is there a way to bind the VisibilityProperty to multiple plots? I would also be interested in the solution involving registering to be notified for handled events, as I could probably just loop through all the plots, and set their VerticalScale property accordingly.
05-17-2013 02:41 PM
For the multiple plots scenario, I would use a MultiBinding
, with a corresponding IMultiValueConverter
to perform the "when all/any plot is collapsed, return collapsed, else visible" logic.
For the handled event registration, you can use this AddHandler
overload, passing true
for the handledEventsToo
parameter (as described in The Concept of Handled section of the WPF Routed Events Overview topic).
05-17-2013 04:07 PM
Great, the MultiBinding solution worked. Thanks for your help.