【问题标题】:Bind Usercontrol contained in a ObservableCollection<CustomClass> in a WrapPanel在 WrapPanel 中绑定 ObservableCollection<CustomClass> 中包含的用户控件
【发布时间】:2014-11-01 21:53:09
【问题描述】:

我有一个这样定义的类:

    public class CustomClass
    {
        string Name;
        int Age;
        Usercontrol usercontrol;
    }

其中 Usercontrol 是我要插入到 WrapPanel 中的可视元素。

CustomClass 被组织在一个静态的 ObservableCollection 中。

    public static class CollectionClass
    {
        public static ObservableCollection<CustomClass> MyCollection = new ObservableCollection<CustomClass>();
    }

我希望将集合中 CustomClass 的 usercontrol 属性绑定到 WrapPanel 中进行可视化,因此我让可视元素以与集合中元素相同的顺序显示。

现在我正在通过代码手动填充 WrapPanel,但我认为必须有一种方法可以通过数据绑定快速轻松地完成它。 我正在尝试使用以这种方式定义的 ItemsControl 来做到这一点:

    <ItemsControl Name="SensorMenuWrap"  ItemsSource="{Binding }">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

但我不知道如何让魔法发生。

编辑:

我尝试了 ChrisO 提出的解决方案,实现方式如下:

1 - 我将集合设为属性

2 - 我将 UserControl 设为属性

3 - 我从代码中设置 DataContex:

SensorMenuWrap.Datacontext = CollectionClass.MyCollection

4 - 绑定:

         <ItemsControl Name="SensorMenuWrap"  ItemsSource="{Binding }">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <ContentControl Content="{Binding usercontrol}" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

现在我可以可视化集合的第一个元素。如果第一个元素发生变化,我将可视化新的第一个元素。如何可视化整个集合?

【问题讨论】:

    标签: wpf data-binding observablecollection wrappanel itemsource


    【解决方案1】:

    我没有测试过这个。此外,请确保 userControl 是属性而不是字段。我假设您知道如何正确设置 DataContext 以引用 MyCollection 属性。

    <ItemsControl Name="SensorMenuWrap"  ItemsSource="{Binding MyCollection}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <ContentControl Content="{Binding userControl}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    

    您还应该考虑直接引用 DataTemplate 中的 UserControl,而不是将其作为类的属性绑定。应该是这样的

    <ItemsControl Name="SensorMenuWrap"  ItemsSource="{Binding MyCollection}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    

    编辑:

    作为对您的编辑的回应,您最好使用可重用的 UserControl 来解决这个问题,该控件在 CustomClass 的属性上带有 DataBindings。这是我必须实现的目标:

    CollectionClass

    public static class CollectionClass
        {
            public static ObservableCollection<CustomClass> MyCollection { get; set; }
    
            static CollectionClass()
            {
                MyCollection = new ObservableCollection<CustomClass>();
    
                MyCollection.Add(new CustomClass { Age = 25, Name = "Hamma"});
                MyCollection.Add(new CustomClass { Age = 32, Name = "ChrisO"});
            }
        }
    

    自定义类

    public class CustomClass
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }
    

    用户控件内容

    <StackPanel>
            <TextBlock Background="Tan" Text="{Binding Name}" />
            <TextBlock Background="Tan" Text="{Binding Age}" />
        </StackPanel>
    

    主窗口

    <ItemsControl Name="SensorMenuWrap"  ItemsSource="{Binding }">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <so25728310:Usercontrol Margin="5" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    

    在这里,您将用户控件保留在视图中,而不是将用户控件烘焙到您的数据中。将视图和数据分开总是好的。您甚至可以取消 Usercontrol 并直接在 DataTemplate 中使用两个 TextBox,但这取决于您是否要在其他地方重用该视图。

    【讨论】:

    • 它将无法正常工作。 MyCollection 本身不是一个属性。他的 DataContext 需要是一个对象,静态类不会提供这个。
    • 不一定,你可以根据需要将元素的DataContext设置为静态类。不过,MyCollection 必须是该静态类的属性。
    • 您的解决方案部分有效。能否请您查看编辑并帮助我修复它?
    • 我不能使用你的方法,因为我在类中有几个 userControls。我写的例子是一个过于简单的例子,以便于理解元素是如何交互的,但是在这一点上我不能改变结构。
    • 我刚刚发现“部分工作”的解决方案是我的坏事:我假设 WrapPanel 在没有明确声明的情况下获取其父级的宽度,而子级水平扩展超出父母。这就是为什么我没有看到它们,我认为只有该系列的第一个元素在展示。该解决方案有效,因此我将其标记为答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    • 2013-12-30
    • 1970-01-01
    相关资源
    最近更新 更多