如何将WPF TextBlock文本绑定到其他属性?

时间:2018-07-25 09:01:14

标签: c# wpf xaml mvvm

基于MVVM模式,我的MODEL中具有这两个属性:

public string DestinationCode

AND

public enum OperatingMode
{
    Unknown,
    [Description("Zzz")]
    Asleep,
    Standby,
    [Description("WKU")]
    WakeUp
}

Senario:我希望显示TextBlock文本:

-目的地代码

-“ Zzz”(如果OperatingMode为“睡眠中”

-“ WKU”(如果OperatingMode为'WakeUp'

2 个答案:

答案 0 :(得分:2)

对于您的财产DestinationCode,绑定需要INotifyPropertychange来提醒他的更改。例如,这是您的课程:

public class Your_Class: INotifyPropertyChanged
{
    private string _destinationCode;
    public string DestinationCode
    {
        get
        {
            return _destinationCode;
        }
        set
        {
            _destinationCode = value;
            RaisePropertyChanged("DestinationCode");
        }
    }

    private OperatingMode _my_Enum;
    public OperatingMode My_Enum
    {
        get
        {
            return _my_Enum;
        }
        set
        {
            _my_Enum = value;
            RaisePropertyChanged("My_Enum");
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

要绑定枚举My_Enum,必须首先创建一个转换器以获取枚举的描述。喜欢的东西:

public class EnumDescriptionConverter : IValueConverter
{
    private string GetEnumDescription(Enum enumObj)
    {
        FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString());

        object[] attribArray = fieldInfo.GetCustomAttributes(false);

        if (attribArray.Length == 0)
        {
            return enumObj.ToString();
        }
        else
        {
            DescriptionAttribute attrib = attribArray[0] as DescriptionAttribute;
            return attrib.Description;
        }
    }

    object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Enum myEnum = (Enum)value;
        string description = GetEnumDescription(myEnum);
        return description;
    }

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return string.Empty;
    }
}

接下来,您的TextBox应该使用此转换器

<TextBox Text="{Binding My_Enum, Converter={StaticResource EnumDescriptionConverter}}"/>

答案 1 :(得分:1)

假定文本应显示DestinationCode,除非OperatingMode设置为具有描述的值:

一种解决方案是使用多重绑定和多值转换器。

示例:

<Window x:Class="WpfApp3.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:local="clr-namespace:WpfApp3"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Width="200"
        Height="150"
        mc:Ignorable="d">
    <Window.Resources>
        <local:DestinationAndOperationModeToDescriptionConverter x:Key="DestinationAndOperationModeToDescription" />
    </Window.Resources>
    <Grid>
        <TextBlock>
            <TextBlock.Text>
                <MultiBinding Converter="{StaticResource DestinationAndOperationModeToDescription}">
                    <Binding Path="DestinationCode" />
                    <Binding Path="OperatingMode" />
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
    </Grid>
</Window>

多值转换器可能看起来像这样:

public class DestinationAndOperationModeToDescriptionConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values == null || values.Length < 2)
        {
            return DependencyProperty.UnsetValue;
        }

        string destinationCode;
        OperatingMode operatingMode;
        if (values[0] is string && values[1] is OperatingMode)
        {
            destinationCode = values[0] as string;
            operatingMode = (OperatingMode)values[1];
        }
        else if (values[1] is string && values[0] is OperatingMode)
        {
            destinationCode = values[1] as string;
            operatingMode = (OperatingMode)values[0];
        }
        else
        {
            return DependencyProperty.UnsetValue;
        }

        var descriptionAttribute =
            typeof(OperatingMode)
                .GetField(operatingMode.ToString())
                .GetCustomAttributes(typeof(DescriptionAttribute), false)
                .OfType<DescriptionAttribute>().FirstOrDefault();

        if (string.IsNullOrEmpty(descriptionAttribute?.Description))
        {
            return destinationCode;
        }

        return descriptionAttribute.Description;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException();
}

ViewModel看起来像这样:

public class MyViewModel : INotifyPropertyChanged
{
    private string destinationCode;
    private OperatingMode operatingMode;

    public event PropertyChangedEventHandler PropertyChanged;

    public string DestinationCode
    {
        get
        {
            return destinationCode;
        }

        set
        {
            if (this.destinationCode == value)
            {
                return;
            }
            destinationCode = value;
            this.OnPropertyChanged();
        }
    }

    public OperatingMode OperatingMode
    {
        get
        {
            return operatingMode;
        }

        set
        {
            if (this.operatingMode == value)
            {
                return;
            }
            operatingMode = value;
            this.OnPropertyChanged();
        }
    }

    private void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}