如何强制工具提示读取绑定

时间:2016-04-04 05:36:18

标签: c# wpf

我有一个大型应用程序,它有很多工具提示。工具提示显示不断变化的数据快照。目前,我通过轮询,然后设置属性并遵循INotifyPropertyChanged模式来重新计算数据的快照。这样做有效,但结果是用户可能会注意到如果数据不幸则数据尚未刷新。此外,该应用程序浪费了大量资源来计算可能永远不会使用的数据快照,因为工具提示没有提出。

这是一个示例应用来证明这一点:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:l="clr-namespace:WpfApplication2"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <l:ViewModel />
    </Window.DataContext>
    <Grid>
        <Button Content="Test"
                ToolTip="{Binding ElapsedTime}" />
    </Grid>
</Window>

使用ViewModel:

public class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        StartTime = DateTime.Now;
    }

    public DateTime StartTime { get; set; }

    public double ElapsedTime { get { return (DateTime.Now - StartTime).TotalSeconds; } }

    protected void RaisePropertyChanged(string prop)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

所以,我的问题是,而不是让一些线程更新&#34; ElapsedTime&#34;在用户需要工具提示的情况下,每秒都有一个属性,XAML中是否有办法说如果需要绑定的值,请务必阅读它吗?

2 个答案:

答案 0 :(得分:1)

更好的方法是使用MouseEnter附加行为并在鼠标悬停时更新ElapsedTime

<强> ViewModel.cs

public class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        StartTime = DateTime.Now;
        UpdateTime = new RelayCommand( UpdateElapsedTime, new Func<bool>(() => { return true; }));
    }

    public DateTime StartTime { get; set; }

    private double _elapsedTime;

    public double ElapsedTime
    {
        get { return _elapsedTime; }
        set { _elapsedTime = value; RaisePropertyChanged("ElapsedTime"); }
    }

    public ICommand UpdateTime { get; set; }

    private void UpdateElapsedTime()
    {
        ElapsedTime = (DateTime.Now - StartTime).TotalSeconds;
    }

    protected void RaisePropertyChanged(string prop)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

<强> MouseEnterBehavior.cs

public static class MouseEnterBehavior
{
    public static readonly DependencyProperty MouseEnterProperty =
       DependencyProperty.RegisterAttached("MouseEnter",
                                           typeof(ICommand),
                                           typeof(MouseEnterBehavior),
                                           new PropertyMetadata(null, MouseEnterChanged));

    public static ICommand GetMouseEnter(DependencyObject obj)
    {
        return (ICommand)obj.GetValue(MouseEnterProperty);
    }

    public static void SetMouseEnter(DependencyObject obj, ICommand value)
    {
        obj.SetValue(MouseEnterProperty, value);
    }

    private static void MouseEnterChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        UIElement uiElement = obj as UIElement;

        if (uiElement != null)
            uiElement.MouseEnter += new MouseEventHandler(uiElement_MouseEnter);
    }

    static void uiElement_MouseEnter(object sender, MouseEventArgs e)
    {
        UIElement uiElement = sender as UIElement;
        if (uiElement != null)
        {
            ICommand command = GetMouseEnter(uiElement);
            command.Execute(uiElement);
        }
    }
}

<强> XAML

<Button Content="Test"
            ToolTip="{Binding ElapsedTime}" local:MouseEnterBehavior.MouseEnter ="{Binding UpdateTime}"/>

MouseEnterBehavior的参考: How can I execute a command binding on MouseEnter of a StackPanel in WPF?

答案 1 :(得分:0)

触发指示更改的事件。

处理此事件以重置您的DataContext

SomeControl.DataContext = null;
SomeControl.DataContext = oldObject; // re-assign your object again