【问题标题】:WPF Binding with converter does not workWPF 与转换器绑定不起作用
【发布时间】:2018-03-26 19:21:46
【问题描述】:

我正在尝试将 XAML 中的一些属性与枚举类型绑定。 它应该如何工作:我在菜单栏中有一些单选按钮,用于设置我的枚举值。这个枚举值在Grid 中设置isEnabled 属性。所以有一个关系:radiobutton ->(EnumToBooleanConverter)-> enum object ->(EnumToIsActiveCnoverter)->isEnabled 属性。我已经编写了两个转换器来执行该绑定。 代码:

<Window.Resources>
    <local:EnumToBooleanConverter x:Key="actionConverter" />
    <local:EnumToIsActiveConverter x:Key="activityConverter" />
</Window.Resources>

...

<MenuItem Header="Settings">
            <MenuItem Header="Action">
                <MenuItem Header="Draw">
                    <MenuItem.Icon>
                        <RadioButton GroupName="MenuActionButton"
                                     IsChecked="{Binding Path=appMode,
                            Converter={StaticResource actionConverter},
                            ConverterParameter={x:Static local:ApplicationMode.Draw}}"/>
                    </MenuItem.Icon>
                </MenuItem>
                <MenuItem Header="Edit">
                    <MenuItem.Icon>
                        <RadioButton GroupName="MenuActionButton"
                                     IsChecked="{Binding Path=appMode,
                            Converter={StaticResource actionConverter},
                            ConverterParameter={x:Static local:ApplicationMode.Edit}}"/>
                    </MenuItem.Icon>
                </MenuItem>
                <MenuItem Header="Constraints">
                    <MenuItem.Icon>
                        <RadioButton GroupName="MenuActionButton"
                                     IsChecked="{Binding Path=appMode,
                            Converter={StaticResource actionConverter},
                            ConverterParameter={x:Static local:ApplicationMode.Constraints}}"/>
                    </MenuItem.Icon>
                </MenuItem>
            </MenuItem>
        </MenuItem>

CS 文件:

public partial class MainWindow : Window
{
    public ApplicationMode appMode { get; set; }

    public MainWindow()
    {
        this.appMode = ApplicationMode.Draw;
        InitializeComponent();
    }
}

public class EnumToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        //return value.Equals(parameter);
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value.Equals(true) ? parameter : Binding.DoNothing;
    }
}
public class EnumToIsActiveConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value.Equals(parameter);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        //return value.Equals(true) ? parameter : Binding.DoNothing;
        return Binding.DoNothing;
    }
}
public enum ApplicationMode
{
    Draw,
    Edit,
    Constraints
}

EnumToBooleanConverter 在选中单选按钮时将枚举值更改为给定参数,当枚举值设置为给定参数时,EnumToIsActiveConverter 更改给定元素的isEnabled 属性。 在我看来,它应该工作得很好。我在这里缺少什么?

【问题讨论】:

    标签: wpf xaml binding converter


    【解决方案1】:

    更简单的解决方案,没有 RadioButton:

    一个。对图标作业使用 MenuItem Checkable 功能,并将 IsChecked 绑定到 appMode 属性:

    <MenuItem Header="Action">
        <MenuItem Header="Draw" IsCheckable="True"
              IsChecked="{Binding Path=appMode,
                                  Converter={StaticResource actionConverter},
                                  ConverterParameter={x:Static local:ApplicationMode.Draw}}" />
    
        <MenuItem Header="Edit" IsCheckable="True"
              IsChecked="{Binding Path=appMode,
                                  Converter={StaticResource actionConverter},
                                  ConverterParameter={x:Static local:ApplicationMode.Edit}}" />
    </MenuItem>
    

    b.在代码中,改变属性触发PropertyChange事件:

    public partial class MainWindow : Window, INotifyPropertyChanged
    {
    
        private ApplicationMode _appMode;
    
        public ApplicationMode appMode
        {
            get { return _appMode; }
            set
            {
                _appMode = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(appMode)));
            }
        }
    
        public MainWindow()
        {
            this.appMode = ApplicationMode.Draw;
            InitializeComponent();
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
    }
    

    c。在转换器中修复 ConvertBack 方法:

    public class EnumToBooleanConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value.Equals(parameter);
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return parameter;
        }
    }
    

    【讨论】:

    • @wis.niowy 你知道怎么接受答案吗?见这里stackoverflow.com/help/someone-answers。根据您的问题历史记录,您有很多问题可以做到这一点,每回答一个问题,您就会获得 +2 声望。
    【解决方案2】:

    您正在使用RadioButton 控件,但仅作为指示器。

    因此,单击项目不会更改属性值,因为只有 MenuItem 会收到 Click,而不是 RadioButton。

    这也有点浪费,因为对于 V(当前活动指示),您不需要 RadioButton 控件,而是具有可见性绑定的 Path。

    我会以现有的方式给你一个解决方案:

    一个。为每个 MenuItem 添加 Click 事件

    b.将相关的值放在 Tag 属性中(这是为了事件的简单性,如您所见)

    c。添加到 INotifyPropertyChanged 接口的 MainWindow 类实现,以使 XAML 知道 appMode 修改。

    这里是代码,XAML:

    <MenuItem Header="Draw" Click="MenuItem_Click" Tag="{x:Static local:ApplicationMode.Draw}" >
        <MenuItem.Icon>
            <RadioButton GroupName="MenuActionButton"
                    IsChecked="{Binding Path=appMode,
        Converter={StaticResource actionConverter},
        ConverterParameter={x:Static local:ApplicationMode.Draw}}"/>
        </MenuItem.Icon>
    </MenuItem>
    <MenuItem Header="Edit" Click="MenuItem_Click" Tag="{x:Static local:ApplicationMode.Edit}">
        <MenuItem.Icon>
            <RadioButton GroupName="MenuActionButton"
                    IsChecked="{Binding Path=appMode,
        Converter={StaticResource actionConverter},
        ConverterParameter={x:Static local:ApplicationMode.Edit}}"/>
        </MenuItem.Icon>
    </MenuItem>
    

    MenuItem_Click for Click 事件:

    public event PropertyChangedEventHandler PropertyChanged;
    
    private void MenuItem_Click(object sender, RoutedEventArgs e)
    {
        var item = (MenuItem)sender;
        appMode = (ApplicationMode) item.Tag;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(appMode)));
    }
    

    【讨论】:

    • 那么如果MenuItem_Click中的appMode属性被修改了,那actionConverter有什么用呢?我需要它吗?
    • 不幸的是,修改后所有DockPanel元素都被启用,这意味着转换器不会改变isEnabled属性
    • 每次更改枚举属性时,PropertyChanged 为 null。
    • 你是否添加了 INotifyPropertyChanged 接口实现声明? public partial class MainWindow : Window, INotifyPropertyChanged
    • 是的,我有。当我在Window 属性中添加x:Name="Self" DataContext="{Binding ElementName=Self}" 时,它开始工作了。我还略微更改了MenuItem(我将很快发布编辑)。谢谢!
    猜你喜欢
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-06
    • 2011-03-13
    • 1970-01-01
    相关资源
    最近更新 更多