【问题标题】:WPF Binding to EnumWPF 绑定到枚举
【发布时间】:2011-05-20 15:54:39
【问题描述】:

我正在尝试学习 WPF 中的一些数据绑定,因此已开始构建一个小的条件生成器测试应用程序,但在弄清楚我的绑定时遇到了一些麻烦。

所以我有一组基于泛型的条件。这是一个简单的 BooleanCondition 示例的类结构。

public abstract class AbstractCondition
{
    /// <summary>
    /// Gets the entry mode.
    /// </summary>
    /// <value>The entry mode.</value>
    public abstract InputFieldMode InputFieldMode { get; }
}

public abstract class GenericCondition<T, O> : AbstractCondition
{
    /// <summary>
    /// Checks the specified value.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public abstract Boolean Check(T value);

    /// <summary>
    /// Gets or sets the value.
    /// </summary>
    /// <value>The value.</value>
    public object Value
    {
        get;
        set;
    }

    /// <summary>
    /// Gets or sets the options.
    /// </summary>
    /// <value>The options.</value>
    public O Option
    {
        get;
        set;
    }

    /// <summary>
    /// Gets the available options.
    /// </summary>
    /// <value>The available options.</value>
    public abstract ObservableCollection<O> AvaliableOptions { get; }
}

/// <summary>
/// Describes a Condition that operations on a Boolean
/// </summary>
/// <typeparam name="U"></typeparam>
public class BooleanCondition : GenericCondition<Boolean?, BooleanConditionOption>
{
    /// <summary>
    /// Initializes a new instance of the <see cref="BooleanCondition&lt;U&gt;"/> class.
    /// </summary>
    /// <param name="option">The option.</param>
    public BooleanCondition(BooleanConditionOption option)
    {
        this.Option = option;
    }

    /// <summary>
    /// Checks the specified value.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public override bool Check(bool? value)
    {
        if (value.HasValue)
        {
            switch (this.Option)
            {
                case BooleanConditionOption.IsFalse:
                    return !value.Value;

                case BooleanConditionOption.IsTrue:
                    return value.Value;
            }
        }

        return false;
    }

    /// <inheritdoc />
    public override InputFieldMode InputFieldMode
    {
        get { return InputFieldMode.NoField; }
    }

    /// <inheritdoc />
    public override ObservableCollection<BooleanConditionOption> AvaliableOptions
    {
        get
        {
            var options = Enum.GetValues(typeof(BooleanConditionOption));
            var optionsCollection = new ObservableCollection<BooleanConditionOption>(options.Cast<BooleanConditionOption>());
            return optionsCollection;
        }
    }
}

目前有 4 个条件,这背后的基本思想是,条件对对象类型进行操作,并提供一组特定于该类型的“条件选项”(布尔有 isTrue、isFalse,而数字可能有 >= 等)。

所以现在我正在尝试创建一个视图,以使 Condition 更易于在 UI 上使用。使用从组合中选择的值调用更新,该组合具有数据类型。那时我构造了适当的条件,并希望通过 ConditionValues 属性公开 ConditionOptions 的集合(因此是枚举的结果,但它可以是 4 个中的任何一个)。

public class ConditionView
    {
        /// <summary>
        /// Gets the Fields that are available for selection.
        /// </summary>
        public ObservableCollection<IDataField> Fields { get; set; }

        public ObservableCollection<Object> ConditionValues { get; set; }

        /// <summary>
        /// Gets the Condition that has been selected.
        /// </summary>
        public AbstractCondition SelectedCondition { get; private set; }

        /// <summary>
        /// Update various options based upon the Selection
        /// </summary>
        /// <param name="field">The IDataField selected</param>
        public void Update(IDataField field)
        {
            if (field != null)
            {
                // Determine what sort of condition we need
                switch (field.Type)
                {
                    case DataType.Boolean:
                        BooleanCondition booleanCondition = new BooleanCondition(BooleanConditionOption.IsFalse);
                        this.SelectedCondition = booleanCondition;
                        this.ConditionValues = booleanCondition.AvaliableOptions;
                        break;

                    case DataType.String:
                        this.SelectedCondition = new StringCondition(StringConditionOption.Contains);
                        break;

                    case DataType.Numeric:
                        this.SelectedCondition = new NumericCondition(NumericConditionOption.Equals);
                        break;

                    case DataType.Date:
                        this.SelectedCondition = new DateCondition(DateConditionOption.Equals);
                        break;

                    default:
                        throw new InvalidOperationException("Unknown Data Type");
                }
            }
        }

我目前只是试图让布尔值运行,但我不确定 ObservableCollection 是否是我应该绑定的(我得到一个构建错误尝试:“错误 5 无法隐式转换类型 'System.Collections .ObjectModel.ObservableCollection' 到 'System.Collections.ObjectModel.ObservableCollection')。我应该如何解决这个绑定问题?最终我有一些转换器也希望在枚举上工作,所以我不确定将结果转换为 Objects 是否正确:S

更新:

尝试将“Fields”绑定到 ComboBox,一旦它改变了对 Update 的调用,将修改绑定到另一个 ComboBox 的“ConditionValues”。

<UserControl x:Class="ConditionBuilder.Views.Condition"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d"
             xmlns:cb="clr-namespace:ConditionBuilder"
             xmlns:wm="clr-namespace:Watermark"
             >
    <UserControl.Resources>
        <cb:EnumToUIConvertor x:Key="enumItemsConverter"/>
    </UserControl.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="229"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <ComboBox x:Name="cmbField" Grid.Column="0" Height="22" Width="120" ItemsSource="{Binding Path=Fields}" SelectionChanged="cmbField_SelectionChanged"> 
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <Label Content="{Binding Path=Name, Mode=OneWay}" Height="Auto" Margin="-5" VerticalAlignment="Stretch"/>
                </DataTemplate>
            </ComboBox.ItemTemplate>
             <wm:Watermark.WatermarkContent>
                <Label Padding="0">Select Field...</Label>
            </wm:Watermark.WatermarkContent>
        </ComboBox>
        <ComboBox x:Name="cmbCondition" Grid.Column="1" Height="22" Width="120" ItemsSource="{Binding Path=ConditionValues, Mode=OneWay}">
            <wm:Watermark.WatermarkContent>
                <Label Padding="0">Select Condition...</Label>
            </wm:Watermark.WatermarkContent>
        </ComboBox>           
    </Grid>
</UserControl>

【问题讨论】:

  • 我不确定你到底想绑定什么。你能发布相关的 XAML 吗?
  • 当然,更新了问题并试图使其更清晰。这是我的“ConditionValues”,它可以包含来自 4 个不同枚举中的 1 个的值。

标签: wpf data-binding


【解决方案1】:

我想我现在明白了。您可能会绑定到SelectedCondition.AvailableOptions 并完全取消ConditionValues。但是,我在您的代码中没有看到任何 INotifyPropertyChanged,因此除非您使用 notifypropertyweaver 或其他技巧,否则您可能需要让 SelectedCondition 引发属性更改事件。

【讨论】:

  • 其实,这是一个非常好的观点。我之前很担心,因为要编译东西,我必须将我的 Enumerable 转换为 IEnumerable 并且认为绑定不会很有效。事实上确实如此。但是完全删除该属性听起来是一个更好的主意。尚未阅读 INotifyPropertyChanged,因此将对此进行深入研究。谢谢。
猜你喜欢
  • 2011-07-03
  • 1970-01-01
  • 2016-03-26
  • 2011-01-30
  • 1970-01-01
  • 2018-12-28
  • 2016-03-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多