当前控件的工具提示中的 WPF C# 状态栏标签内容

Posted

技术标签:

【中文标题】当前控件的工具提示中的 WPF C# 状态栏标签内容【英文标题】:WPF C# Statusbar label content from current control's tooltip 【发布时间】:2018-02-10 18:37:02 【问题描述】:

好的,所以我想弄清楚如何设置状态栏标签文本以显示有关鼠标悬停的当前控件的信息。我在很多程序上都看到过很多次,所以我知道这是可以做到的,我相信那里有可以帮助我的解释,但不幸的是,我似乎找不到合适的词来寻找答案...... 我能找到的最接近的东西在下面的链接中。我尝试使用它,但是当我尝试设置 text 属性时它给了我一个错误。

有人有一些信息或链接可以帮助我吗? 谢谢, 瑞恩

Display text in a label when hovering over a control without using events

我的 XAML 代码:

<StatusBar>
            <StatusBar.ItemsPanel>
                <ItemsPanelTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="75" />
                        </Grid.ColumnDefinitions>

                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                    </Grid>
                </ItemsPanelTemplate>
            </StatusBar.ItemsPanel>
            <StatusBarItem Grid.Column="0">
                <Label Content="New Lead Inquiry" />
            </StatusBarItem>
            <Separator Grid.Column="1" Style="StaticResource StylingStatusBarSeparator" />
            <StatusBarItem Grid.Column="2">
                <Label x:Name="infoStatusBar" Content="Label for text about the currently hovered item" />
            </StatusBarItem>
            <Separator Grid.Column="3" Style="StaticResource StylingStatusBarSeparator" />
            <StatusBarItem Grid.Column="4">
                <Label Content="Not Saved" />
            </StatusBarItem>
        </StatusBar>

【问题讨论】:

“它给了我一个错误” -- 你有没有注意到错误是什么? 运行程序时没有报错。是否可能是因为我将 style 属性设置为 StaticResource 设置,而当您运行它时它没有该 Resource? 什么时候给你的错误? 您是在使用 MVVM,还是在使用后面的代码?无论哪种情况,我认为您可以使用控件上的 MouseEnter 和 MouseLeave 事件来设置或清除状态栏文本。如果你给我一个关于你如何构建你的项目的提示,我可以提供示例代码。 哦!!!对不起,当你说它给我一个错误时,我误解了你的意思。当我尝试使用有关“ 的链接中提供的代码时,它说属性“Text”无法识别或无法访问。 【参考方案1】:

这是一个不需要您修改每个子控件或使用任何框架的解决方案。

这与 MVVM 并没有真正的关系,因为它是纯 UI 的东西。这里没有涉及视图模型的内容。

句柄 Window.PreviewMouseMove:

MainWindow.xaml

<Window 
    ...
    PreviewMouseMove="Window_PreviewMouseMove"
    >

MainWindow.xaml.cs

定义一个 Object 类型的依赖属性,并在预览 mousemove 处理程序中,为其提供鼠标所在控件最近的父工具提示:

    private void Window_PreviewMouseMove(object sender, MouseEventArgs e)
    
        var element = Mouse.DirectlyOver as FrameworkElement;

        HoverToolTip = GetTooltip(element);  
    

    #region HoverToolTip Property
    public object HoverToolTip
    
        get  return (object)GetValue(HoverToolTipProperty); 
        set  SetValue(HoverToolTipProperty, value); 
    

    public static readonly DependencyProperty HoverToolTipProperty =
        DependencyProperty.Register(nameof(HoverToolTip), typeof(object), typeof(MainWindow),
            new PropertyMetadata(null));
    #endregion HoverToolTip Property

    protected static Object GetTooltip(FrameworkElement obj)
    
        if (obj == null)
        
            return null;
        
        else if (obj.ToolTip != null)
        
            return obj.ToolTip;
        
        else
        
            return GetTooltip(VisualTreeHelper.GetParent(obj) as FrameworkElement);
        
    

并将其绑定到 XAML 中的任何内容。

    <Label
        x:Name="StatusBar"
        Content="Binding HoverToolTip, RelativeSource=RelativeSource AncestorType=Window"
        Grid.Row="2"
        />

该标签只是我在测试 XAML 中放入的快速工具。这个绑定是其中的重要部分:

Binding HoverToolTip, RelativeSource=RelativeSource AncestorType=Window

【讨论】:

【参考方案2】:

您可以连接控件上的MouseEnterMouseLeave 命令以在视图模型中设置HelpText 属性,然后将状态栏标签绑定到HelpText,以便在设置为新内容时,新值出现在状态栏中。

此答案使用 MVVM Light 工具包,但应该适用于任何 MVVM 设置:

在 XAML 中:

<Window x:Class="MvvmLightPlayground.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:ignore="http://www.galasoft.ch/ignore"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        mc:Ignorable="d ignore"
        Height="300"
        Width="600"
        Title="MVVM Light Application">


    <Window.DataContext>
        <Binding Path="Main" Source="StaticResource Locator" />
    </Window.DataContext>

    <StackPanel>
        <Label Content="This is Label1" x:Name="Label1">
            <!-- Triggers like this are easy to wire up using blend.  If you do it manually, add the i: definition to your window tag as shown above -->
            <i:Interaction.Triggers>
                <i:EventTrigger SourceName="Label1" EventName="MouseEnter">
                    <i:InvokeCommandAction Command="Binding MouseEnter" CommandParameter="This is Label1.  Look how neat it is!" />
                </i:EventTrigger>
                <i:EventTrigger SourceName="Label1" EventName="MouseLeave">
                    <i:InvokeCommandAction Command="Binding MouseLeave" CommandParameter="This is Label1.  Look how neat it is!" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Label>
        <Label Content="This is Label2" x:Name="Label2">
            <i:Interaction.Triggers>
                <i:EventTrigger SourceName="Label2" EventName="MouseEnter">
                    <i:InvokeCommandAction Command="Binding MouseEnter" CommandParameter="This is Label2.  It's a different label." />
                </i:EventTrigger>
                <i:EventTrigger SourceName="Label2" EventName="MouseLeave">
                    <i:InvokeCommandAction Command="Binding MouseLeave" CommandParameter="This is Label2.  It's a different label." />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Label>

        <StatusBar>
            <StatusBar.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </StatusBar.ItemsPanel>
            <StatusBarItem>
                <Label Content="Binding HelpText, Mode=OneWay" /> <!-- Bind to your HelpText property in the VM -->
            </StatusBarItem>
        </StatusBar>
    </StackPanel>
</Window>

在您的视图模型中:

首先,为 HelpText 和 ICommand 添加属性:

private string _helpText = "Testing";
public string HelpText

    get
    
        return _helpText;
    
    set
    
        Set(() => HelpText, ref _helpText, value);
    


private ICommand _mouseEnter;
public ICommand MouseEnter

    get
    
        return _mouseEnter;
    
    set
    
        Set(() => MouseEnter, ref _mouseEnter, value);
    


private ICommand _mouseLeave;
public ICommand MouseLeave

    get
    
        return _mouseLeave;
    
    set
    
        Set(() => MouseLeave, ref _mouseLeave, value);
    

然后在 viewmodel 构造函数中初始化 ICommands 以指向 viewmodel 中的方法:

public MainViewModel()

    MouseEnter = new RelayCommand<string>(SetHelpText);
    MouseLeave = new RelayCommand<string>(ClearHelpText);

然后创建帮助方法来设置 HelpText 属性:

public void SetHelpText(string helpText)

    HelpText = helpText;


public void ClearHelpText(string textToClear)

    // check to see whether it has already been set to something else by another MouseEnter event...
    if (HelpText == textToClear)
    
        HelpText = "";
    

这是鼠标悬停在Label2上时显示的运行示例:

【讨论】:

哦,伙计...这是很多我不熟悉的东西,但我会努力解决它,看看我是否可以让它发挥作用。谢谢您的帮助。之后我会更新状态。 :) 如果您想这样做,请从mvvmlight.net(或可能的 NuGet)获取 MVVMLight 工具包。它有据可查,创建者做了一个优秀的 Pluralsight 课程(我使用免费试用版来查看),这让我加快了速度。如果没有该工具包,这一切都是可能的,但必须对其进行修改 - 基本上依赖于它的部分是 Set(() =&gt; HelpText, ref _helpText, value) 设置器(它会自动为您实现 INotifyPropertyChanged)和 RelayCommands,这使得连接更容易up 命令绑定到 viewmodel 代码。 大声笑,我确实尽力了!我的 ViewModel 的 StatusBarHelpText.cs 文件遇到问题。您希望我放置的部分 Set(() => MouseEnter, ref _mouseEnter, value);它说名称“Set”在当前上下文中不存在。此外, MainView() 部分说它需要一个返回类型,然后 RelayCommand 询问我是否缺少 using 指令或程序集引用。我确定这只是我应该添加的内容,但我不确定那是什么……这是文件的 GitHub 链接。 github.com/G33kman/RI 哈哈!!!好的,所以我假设那是我的问题......我会研究 mvvmlight 灯。 是的,Set 是 MVVMLight 工具包的一部分,而不是 .Net 的一部分。如果您不使用它,只需确保您的 setter 正在调用 INotifyPropertyChanged,否则您的更改将不会显示在 UI 中。 MainViewModel() 是一个构造函数 - 确保它的名称与类名匹配,以便编译器知道它是一个构造函数。如果您的类名为 StatusBarHelpText,而您的方法名为 MainView(),那么它将期望返回类型,因为这些名称不匹配。

以上是关于当前控件的工具提示中的 WPF C# 状态栏标签内容的主要内容,如果未能解决你的问题,请参考以下文章

如何在wpf C#中保持用户控件的当前状态

C#winform如何实现状态栏

WPF,从用户控件中更新主窗口中的状态栏

强制 WPF 工具提示留在屏幕上

WPF用户控件嵌套控件-从用户控件切换用户控件

C# wpf 实现任意控件拖动