WPF与转换器绑定不起作用

时间:2017-10-15 00:17:29

标签: wpf xaml binding converter

我试图用枚举类型绑定XAML中的一些属性。 它应该如何工作:我在菜单栏中有一些单选按钮,用于设置我的枚举值。此枚举值会在isEnabled中设置Grid属性。所以有一个关系:radiobutton - >(EnumToBooleanConverter) - >枚举对象 - >(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会在检查radiobutton时将枚举值更改为给定参数,并且EnumToIsActiveConverter更改给定元素的isEnabled属性。 在我看来它应该工作得很好。我在这里缺少什么?

2 个答案:

答案 0 :(得分:1)

您正在使用RadioButton控制,但仅作为指标。

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

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

我将以现有方式向您介绍解决方案:

一个。将Click事件添加到每个MenuItem

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

℃。添加到您的MainWindow类实现INotifyPropertyChanged接口,以便让XAML了解appMode modofication。

这里是代码,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)));
}

答案 1 :(得分: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>

湾在代码中,更改属性以触发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;

}

℃。在转换器中修复ConvertBack metode:

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;
    }
}