WPF MVVM中重用属性方法的一种简单方法

本文关键字:方法 一种 简单 属性 WPF MVVM | 更新日期: 2023-09-27 18:00:00

我是WPF MVVM的新手。以下是我的视图模型正在做的事情:

按下按钮并启动ping命令以查看服务器是否可用:

-如果为true,则该按钮设置为"隐藏"。

-如果为false,则会将带有消息("Servers not available")的标签设置为可见

如何重用以下IsVisible方法来设置标签的可见性?

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Input;
namespace WpfTest
{
    public class PrnViewModel1 : ViewModelBase
    {
        private ICommand m_PrnServPingCommand;
        private Visibility _isVisible=Visibility.Visible;

        public PrnViewModel1()
        {
            PrnServPingCommand = new RelayCommand(new Action<object>(PrnServPing));
        }
        public ICommand PrnServPingCommand
        {
            get
            {
                return m_PrnServPingCommand;
            }
            set
            {
                m_PrnServPingCommand = value;
            }
        }
        public void PrnServPing(object obj)
        {
            string[] serverNames = { "svmsimp1", "svmsimp2" };
            bool serversArePingable = Cmethods.PingableAll(serverNames);
            if (serversArePingable)
            {
                IsVisible = Visibility.Hidden; //Button is Hidden
            }
            else
            {
                //*** Label with Message "Servers not pingable" set to visible
            }
        }
        public Visibility IsVisible
        {
            get
            {
                return _isVisible;
            }
            set
            {
                _isVisible = value;
                OnPropertyChanged("IsVisible");
            }
        }
    }
}

WPF MVVM中重用属性方法的一种简单方法

您可以使用IValueConverter反转标签上的Visibility

下面是一个示例实现:

public static class Extensions
{
    public static System.Windows.Visibility Reversed(this System.Windows.Visibility visibility)
    {
        if (visibility == System.Windows.Visibility.Visible)
            visibility = System.Windows.Visibility.Collapsed;
        else if (visibility == System.Windows.Visibility.Collapsed || visibility == System.Windows.Visibility.Hidden)
            visibility = System.Windows.Visibility.Visible;
        return visibility;
    }
}
public class VisibilityReversedConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((System.Windows.Visibility)value).Reversed();
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((System.Windows.Visibility)value).Reversed();
    }
}

用法:

<TextBlock Text="Servers not available" Visibility="{Binding Visibility, Converter={StaticResource VisibilityReversedConverter}}" ... />

不要忘记实例化Resources中的转换器。有关转换器的教程,请参阅此处。

我自己经常在ViewModel中使用Visibility类型(因为Hidden != Collapsed,所以避免编写转换器来控制布局)。

这里需要的是两个属性来控制标签和按钮的可见性,或者一个属性(bool)来切换显示的属性和转换器(带参数反转或只有两个转换器)。

以下是使用转换器和参数(奖金-MarkupExtension!)的解决方案:

public class SuperConverter : MarkupExtension, IValueConverter
{
    public SuperConverter() { }
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool)
        {
            bool inverted = false;
            if (parameter != null && parameter.ToString().Contains("Inverted"))
                inverted = true;
            return (inverted && (bool)value || !inverted && !((bool)value)) ? Visibility.Hidden : Visibility.Visible;
        }
        throw new InvalidCastException();
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

并使用它(您必须在ViewModel中具有bool IsOperationInProgress,该值将切换文本或按钮的显示):

<TextBlock Visibility="{Binding IsOperationInProgress, Converter={l:SuperConverter}}" ... />
<Button Visibility="{Binding IsOperationInProgress, Converter={l:SuperConverter}, ConverterParameter=Inverted}" ... />