问题
I have a function in .xaml.cs which i wanted to call:
.xaml.cs
private void treeView_SelectedItemChanged(object sender, EventArgs e)
{
//treeView.ScrollToCenterOfView(sender as TreeViewItem);
}
like from this post: Make ListView.ScrollIntoView Scroll the Item into the Center of the ListView (C#) Answer 1
But i dont use the SelectedItem, my approach would be like:
XAML:
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive}" Value="true">
// ###call this function
</DataTrigger>
</Style.Triggers>
I dont have any Idea how to raise this function by change of the DataModel. In every Tutorial i have gooled they do it via Event/Command.
Thx
回答1:
Just to add another slightly hacky option for these scenarios.
Not quite a Trigger, but you can utilise the generic FrameworkElement.Tag property to set up a binding for the property you want to watch, and then run a callback when it changes.
eg:
<DataTemplate>
<StackPanel Tag="{Binding IsActive, NotifyOnTargetUpdated=True}"
TargetUpdated="CodeBehindMethodToCall">
<!-- snip rest of template -->
</StackPanel>
<DataTemplate>
回答2:
Here's my solution for an Auto-ScrollItemToCenter TreeView with a DataTrigger, so it's not the selected item which scrolls.
In XAML i added a custom Behavior via DataTrigger
<Style TargetType="TreeViewItem" BasedOn="{StaticResource {x:Type TreeViewItem}}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelectedInGrid}" Value="true">
<Setter Property="local:TreeViewScrollBehavior.ScrollItemToCenter" Value="true" />
</DataTrigger>
</Style.Triggers>
I tried to create my own behavior after this simple example from http://www.shujaat.net/2010/08/attached-behaviors.html
public static class TreeViewScrollBehavior
{
public static DependencyProperty ScrollItemToCenterProperty =
DependencyProperty.RegisterAttached("ScrollItemToCenter", typeof(bool),
typeof(TreeViewScrollBehavior), new UIPropertyMetadata(false, OnScrollItemToCenter));
public static bool GetScrollItemToCenter(DependencyObject obj)
{
return (bool)obj.GetValue(ScrollItemToCenterProperty);
}
public static void SetScrollItemToCenter(DependencyObject obj, bool value)
{
obj.SetValue(ScrollItemToCenterProperty, value);
}
public static void OnScrollItemToCenter(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
//TreeViewItem t = GetTreeViewItem(d);
TreeViewItem t = (TreeViewItem)d;
TryScrollToCenterOfView(GetTree(t), t);
}
}
and added the slightly changed functions of the above mentioned link
private static TreeView GetTree(TreeViewItem item)
{
var parent = VisualTreeHelper.GetParent(item);
while (!(parent is TreeView))
{
parent = VisualTreeHelper.GetParent(parent);
}
return parent as TreeView;
}
private static void TryScrollToCenterOfView(ItemsControl itemsControl, UIElement container)
{
// Find the container
//var container = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as UIElement;
if (container == null) return;
// Find the ScrollContentPresenter
ScrollContentPresenter presenter = null;
for (Visual vis = container; vis != null && vis != itemsControl; vis = VisualTreeHelper.GetParent(vis) as Visual)
if ((presenter = vis as ScrollContentPresenter) != null)
break;
if (presenter == null) return;
// Find the IScrollInfo
var scrollInfo =
!presenter.CanContentScroll ? presenter :
presenter.Content as IScrollInfo ??
FirstVisualChild(presenter.Content as ItemsPresenter) as IScrollInfo ??
presenter;
// Compute the center point of the container relative to the scrollInfo
Size size = container.RenderSize;
Point center = container.TransformToAncestor((Visual)scrollInfo).Transform(new Point(size.Width / 2, size.Height / 2));
center.Y += scrollInfo.VerticalOffset;
center.X += scrollInfo.HorizontalOffset;
// Adjust for logical scrolling
if (scrollInfo is StackPanel || scrollInfo is VirtualizingStackPanel)
{
double logicalCenter = itemsControl.ItemContainerGenerator.IndexFromContainer(container) + 0.5;
Orientation orientation = scrollInfo is StackPanel ? ((StackPanel)scrollInfo).Orientation : ((VirtualizingStackPanel)scrollInfo).Orientation;
if (orientation == Orientation.Horizontal)
center.X = logicalCenter;
else
center.Y = logicalCenter;
}
// Scroll the center of the container to the center of the viewport
if (scrollInfo.CanVerticallyScroll) scrollInfo.SetVerticalOffset(CenteringOffset(center.Y, scrollInfo.ViewportHeight, scrollInfo.ExtentHeight));
if (scrollInfo.CanHorizontallyScroll) scrollInfo.SetHorizontalOffset(CenteringOffset(center.X, scrollInfo.ViewportWidth, scrollInfo.ExtentWidth));
}
private static double CenteringOffset(double center, double viewport, double extent)
{
return Math.Min(extent - viewport, Math.Max(0, center - viewport / 2));
}
private static DependencyObject FirstVisualChild(Visual visual)
{
if (visual == null) return null;
if (VisualTreeHelper.GetChildrenCount(visual) == 0) return null;
return VisualTreeHelper.GetChild(visual, 0);
}
That's my complete solution to scroll a TreeView without Code in xaml.cs or the DataObject.
Thx for the idead of Behaviors to the user AwkwardCoder
If anyone has some tipps for improvement, i like to hear it ;-)
回答3:
I think you can not. DataTrigger are there to change the WPF level presentation, only. The standard approach is to use what the control provide as events.
回答4:
The TreeViewItem class has an IsSelected and importantly an Selected event, so in theory you could set up and event handler for the Selected event on the TreeViewItem when they are created.
Hopefullt this should be obvious this will not work in an MVVM secenario as you won't have access to the created TreeViewItem instance, in this case I would be looking to do this with a Behaviour for the TreeView control.
来源:https://stackoverflow.com/questions/26037276/can-i-call-a-function-via-datatrigger-xaml