Can i call a function via DataTrigger (XAML)?

浪尽此生 提交于 2021-02-18 17:08:23

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!