【问题标题】:Tooltip on button click while button is disabled禁用按钮时单击按钮的工具提示
【发布时间】:2016-12-12 15:38:18
【问题描述】:

有一个导航命令需要在点击时显示一个工具提示,同时被禁用,以便用户知道它为什么被禁用。我遇到的问题是我不知道如何将 TouchDown 事件从我的 xaml 文件传递​​到我的视图模型。有什么方法可以绑定而不是在 command.xaml.cs 中创建事件?

命令的结构如下。我有一个 CommandButton.xaml 和 CommandButton.xaml.cs,而设置按钮的所有内容都由 VM(文本、图像、执行的命令等)代码处理,如下面的示例。

<Button Focusable="True" Name="Btn1" Command="{Binding CommandToExecute}" Tag="{Binding Text}" Foreground="{x:Null}" Style="{DynamicResource ButtonStyle}" ToolTipService.ShowOnDisabled="true" TouchDown="Btn1_OnTouchDown" >
    <Button.ToolTip>
        <StackPanel>
            <TextBlock>Test</TextBlock>
            <TextBlock>Load stencil, or not your choice.</TextBlock>
        </StackPanel>
    </Button.ToolTip>
    <shellModule:AutoGreyableImage  Source="{Binding Image}" />
</Button>

至于后面的代码,我将其与基本命令类中的大多数处理程序内容进行了拆分,如下所示。

public abstract class BaseCommand : BindableBase
{
    protected IModuleManager ModuleManager { get; set; }

    protected IRegionManager RegionManager { get; set; }

    protected BaseCommand(IRegionManager regionManager, IModuleManager moduleManager, string pageName = null)
    {
        RegionManager = regionManager;
        ModuleManager = moduleManager;
        Text = GetButtonText(pageName + "_BtnTxt");
        Image = (ImageSource)Application.Current.FindResource(pageName + "_BtnImg");
    }

    private string _text;

    private ImageSource _image;

    public ICommand CommandToExecute => new DelegateCommand<object>(Command, Evaluate);

    protected abstract void Command(object obj);

    protected virtual bool Evaluate(object obj)
    {
        return false;
    }

    public string Text
    {
        get { return _text; }
        set { SetProperty(ref _text, value); }
    }

    public ImageSource Image
    {
        get { return _image; }
        set { SetProperty(ref _image, value); }
    }

    protected string GetButtonText(string key)
    {
        string uiString;
        var locExtension = new LocTextExtension
        {
            Key = "Resources",
            ResourceIdentifierKey = key
        };
        locExtension.ResolveLocalizedValue(out uiString);
        return uiString;
    }
}

然后是视图模型中的命令特定内容。

public class Page1CommandViewModel : BaseCommand, IPage1CommandViewModel
{
    public Page1CommandViewModel(IRegionManager regionManager, IModuleManager moduleManager) : base( regionManager, moduleManager, PageNames.Page1 )
    {
    }

    protected override void Command(object obj)
    {
        Task.Run(() =>
        {
            ModuleManager.LoadModule(ModuleNames.Page1Module);
            RegionManager.RequestNavigate(RegionNames.ContentRegion, new Uri(PageNames.Page1, UriKind.Relative));
        });
    }
}

如果有人能指出我正确的方向,将不胜感激。

【问题讨论】:

  • 点击工具提示很奇怪。为什么不将按钮包装在显示工具提示的某个面板中?这样即使按钮本身被禁用,它也将是可见的。
  • 应用程序将在触摸屏上运行,这就是为什么需要点击而不是悬停的原因。
  • 那不是真的“点击”,是吗? Tooltip 在触摸 UI 中不是一个方便的解决方案。如果您确实需要以这种方式显示信息,为什么不完全禁用该按钮,并根据某些条件在用户单击它时显示一些消息?
  • 取决于我们获得的触摸屏。我们过去(可能在未来)使用的电阻式不会将手指按压转化为触摸事件,而是转化为点击事件。或者至少看起来是这样。我认为它们只在电容屏上注册为触摸事件(我可能错了)

标签: c# wpf xaml mvvm


【解决方案1】:

也许不是禁用按钮,而是将按钮重新指向不同的方法,然后显示您的错误/工具提示消息。 (然后,您可以在方法参数/变量中传入说明不活动原因的字符串。)

我还建议您更改按钮的类/视觉属性,使其看起来被禁用。

【讨论】:

  • 是的,我曾认为这是解决问题的一种潜在方法。只是希望有某种方法可以在没有烟雾和镜子的情况下工作,但目前这是我的后备计划(同事已经有一个以相同方式工作的工作原型。)
  • 是的,关于工具提示的位置/可行性存在一个完整的争论。似乎很奇怪,似乎没有标准,甚至没有对它们的合法需求的共同看法。 stackoverflow.com/questions/1737773/…
  • 嗯,您的回答确实帮助我找到了一些可行的方法。我现在将按钮包装在内容控件中,并将工具提示分配给内容控件。这样按钮可以被禁用,但内容控制仍然可以为我处理事件。
  • 另外看看你链接的那个帖子,他们错过了一个很大的部分,触摸屏和工具提示都经常需要。制造业(这个应用程序的用途)。硬件位置不正确,设置不正确,影响显示哪些控件的许多变量意味着工具提示几乎是必需的。
【解决方案2】:

经过多次谷歌搜索,我自己想出了一个解决方案,部分归功于其他人引导我走向正确方向的 cmets。将我的按钮包装在 contentControl 中,而是将工具提示应用于此。

<ContentControl MouseDown="ContentControl_MouseDown">
    <ContentControl.ToolTip>
        <ToolTip Placement="Mouse" Content="Testing" />
    </ContentControl.ToolTip>
    <Button Focusable="True" x:Name="Btn1" Command="{Binding CommandToExecute}" Tag="{Binding Text}" Foreground="{x:Null}" Style="{DynamicResource ButtonStyle}" ToolTipService.ShowOnDisabled="true">
        <shellModule:AutoGreyableImage  Source="{Binding Image}" />
    </Button>
</ContentControl>

并且在 button.xaml.cs 上放置事件来处理按钮点击等的时间。

    Timer Timer { get; set; }
    ToolTip toolTip { get; set; }

    public CommandButton()
    {
        InitializeComponent();
        Timer = new Timer {Interval = 3000};
        Timer.Elapsed += OnTimerElapsed;
    }

    private void CloseToolTip()
    {
        if (toolTip != null)
        {
            toolTip.IsOpen = false;
        }
    }

    private void OnTimerElapsed(object sender, ElapsedEventArgs e)
    {
        Timer.Stop();
        Application.Current.Dispatcher.BeginInvoke((Action)CloseToolTip, DispatcherPriority.Send);
    }

    private void ContentControl_MouseDown(object sender, MouseButtonEventArgs e)
    {
        toolTip = ((ToolTip)((Control)sender).ToolTip);
        toolTip.IsOpen = true;
        Timer.Start();
    }

从以下位置获取的计时器。

https://social.msdn.microsoft.com/Forums/vstudio/en-US/9e3eb4ab-ed0f-40ad-ad47-a1fff8e0fe8d/tooltips-in-wpf-touch-applications?forum=wpf

这允许按钮被禁用,并且工具提示仍然在点击时显示。我现在需要做的就是将工具提示内容包装在一个绑定中并在悬停时禁用工具提示(不是必需的),这一切都解决了。

不过,暂时保留问题,因为可能会出现更好的解决方案。

【讨论】:

  • 好吧,事实证明这也不是一个理想的解决方案。无法使工具提示与绑定一起使用。没有文字可以理解,可能需要进一步研究。
  • 啊,直接在 ContentControl 上设置 tooltip = {Binding blah} 工作正常,只有当我尝试在 ContentControl.Tooltip 标签内绑定它时它才会失败。仍然不知道有什么区别,但这符合我的目的。
猜你喜欢
  • 1970-01-01
  • 2012-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-08
  • 1970-01-01
相关资源
最近更新 更多