【问题标题】:How to bind a list of child objects in Silverlight MVVM如何在 Silverlight MVVM 中绑定子对象列表
【发布时间】:2011-05-18 13:10:26
【问题描述】:

在 Silverlight、MVVM 中,我必须创建一个属性窗口,但我只有一个 List<AProperty> 对象,其中AProperty 是一个带有一些子类的抽象类。

我想将它绑定到 Silverlight 控件(但绑定到哪个控件?),但有一些条件:

  1. 一些子属性必须显示为文本框,一些显示为复选框,一些显示为组合框。它来自动态类型。
  2. AProperty 类有一个PropertyGroup 和一个Name 字段。顺序必须是字母 (PropertyGroup > Name)

任何想法或工作示例?

我的代码:

    public abstract class AProperty {
        private String _Name;
        private String _Caption;
        private String _PropertyGroup;

        public String Name {
            get { return _Name; }
            set { _Name = value; }
        }

        public String Caption {
            get { return _Caption; }
            set { _Caption = value; }
        }

        public String PropertyGroup {
            get { return _PropertyGroup; }
            set { _PropertyGroup = value; }
        }
    }
    List<AProperty> Properties;

还有 xaml:

<ListBox ItemsSource="{Binding ... Properties ...}">
  <!-- Here order the items -->
  <ListBox.ItemTemplate>
    <DataTemplate>
      <StackPanel Orientation="Horizontal">
        <TextBlock Width="250"
                    Text="{Binding Path=Caption}" />

        <!-- And here need I a textbox, or a checkbox, or a combobox anyway -->
      </StackPanel>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

我发现值转换器仅适用于控件属性,而不适用于整个堆栈面板内容。

【问题讨论】:

  • 问题仍然存在,是否可以对xaml代码中的元素进行排序?

标签: silverlight mvvm bind


【解决方案1】:

您可以使用值转换器来检查对象是什么类型并返回正确的控件类型。

您有任何示例代码,以便我提供更好的示例吗?

【讨论】:

  • 我已经添加了我的“代码”。现在有什么想法吗?我认为,价值转换器并不能解决这个问题。
  • 如何添加所有控件并使用 Visibility ValueConverter 来确定哪个是可见的?您是否通过 AProperty 类的属性之一来确定?如果你告诉我显示控件的逻辑,我可以写一个例子来说明我的意思。
  • 不,控件的类型取决于动态类型。这个显示隐藏解决方案看起来不错,但不是很漂亮:)
  • 我同意这不是一个很好的解决方案,但我还没有找到更好的解决方案来根据绑定显示不同的控件。我很想知道人们提出了哪些其他解决方案。
【解决方案2】:

安迪提到的 ValueConverter 应该可以工作。在你的文本块下面有一个 ContentPresenter,并绑定它的内容。

Content={Binding,ConverterParameter={StaticResource NAMEOFCONVERTER}}。

与属性的绑定是空的,因为您已经将所需的对象作为上下文。然后只需检查类型并返回您想要的控件。您可能想要制作只是文本块等的用户控件,以便您可以在那里设置绑定,否则您将不得不在代码中进行。

【讨论】:

  • 我是 SL/xaml 的新手,你能给我发个例子吗?
  • public class YOURCONVERTER: IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfoculture) { //取决于,但你可以对“值”执行 GetType(),然后类似于: } public object ConvertBack(object value, Type targetType, object parameter, CultureInfoculture) { throw new NotImplementedException(); } }
【解决方案3】:

感谢 Jesse 和 Andy,这是解决方案

转换器:

public class PropertyConverter : IValueConverter {
        public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) {
            Binding ValueBinding = new Binding() {
                Source = value,
                Path = new PropertyPath( "Value" ),
                Mode = BindingMode.TwoWay
            };

            Binding EditableBinding = new Binding() {
                Source = value,
                Path = new PropertyPath( "Editable" ),
                Mode = BindingMode.TwoWay
            };

            if( value is PropertyString ) {
                TextBox tb = new TextBox();
                tb.SetBinding( TextBox.TextProperty, ValueBinding );
                tb.SetBinding( TextBox.IsEnabledProperty, EditableBinding );

                return tb;
            } else if( value is PropertyBoolean ) {
                CheckBox cb = new CheckBox();
                cb.SetBinding( CheckBox.IsCheckedProperty, ValueBinding );
                cb.SetBinding( CheckBox.IsEnabledProperty, EditableBinding );

                return cb;
            } ....

            return null;
        }

        public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) {
            throw new NotImplementedException();
        }
    }

还有xaml代码:

...
xmlns:Converters="clr-namespace:MyConverters"
...

<UserControl.Resources>
    <Converters:PropertyConverter x:Key="PropertyInput"/>
</UserControl.Resources>

...

<ListBox ItemsSource="{Binding Path=ItemProperties.GeneralProperties}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="180" />
                            <ColumnDefinition Width="320" />
                        </Grid.ColumnDefinitions>

                        <TextBlock Text="{Binding Name}" Grid.Column="0" />
                        <ContentPresenter Content="{Binding Converter={StaticResource PropertyInput}}" Grid.Column="1" />
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

两篇文章: http://shawnoster.com/blog/post/Dynamic-Icons-in-the-Silverlight-TreeView.aspx http://www.silverlightshow.net/items/Silverlight-2-Getting-to-the-ListBoxItems-in-a-ListBox.aspx

【讨论】:

  • 有趣。我以前从未见过这样使用过的 ContentPresenter。很酷。感谢您发布解决方案。
  • 我之前没见过 ContentPresenter :)
猜你喜欢
  • 1970-01-01
  • 2015-01-16
  • 2013-12-17
  • 1970-01-01
  • 1970-01-01
  • 2011-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多