【问题标题】:Multiple ItemsControls bound to same collection on VM doesn't render properly绑定到 VM 上同一集合的多个 ItemsControl 无法正确呈现
【发布时间】:2014-01-30 01:02:56
【问题描述】:

我遇到了一个我认为可能是 WPF 错误的问题。我有一个 WPF 视图,其中包含两个 ItemsControl 元素,它们的 ItemsSource 属性都绑定到 ViewModel 上的同一个 ObservableCollection 属性。我看到的行为是只有在 XAML 中最后声明的 ItemsControl 才能正确呈现其内容。

我的视图包含以下内容:

<Window x:Class="ItemsControlBindingTest.Views.ItemsControlBindingTestView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ItemsControlBindingTestView" Height="300" Width="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" Grid.ColumnSpan="2" TextWrapping="Wrap">
            Note that of the two ItemsControls in this view, only the last declared in XAML renders its contents properly.
        </TextBlock>
        <ItemsControl Grid.Column="0" Grid.Row="1" ItemsSource="{Binding ButtonList}"/>
        <ItemsControl Grid.Column="1" Grid.Row="1" ItemsSource="{Binding ButtonList}"/>
    </Grid>
</Window>

您可以看到我只是得到了一个带有文本块和两个 ItemsControl 的网格 - 每个都绑定到 ViewModel 上的相同属性。

View 的代码隐藏非常简单: 使用 System.Windows; 使用 ItemsControlBindingTest.ViewModels;

namespace ItemsControlBindingTest.Views
{
    /// <summary>
    /// Interaction logic for ItemsControlBindingTestView.xaml
    /// </summary>
    public partial class ItemsControlBindingTestView : Window
    {
        public ItemsControlBindingTestView()
        {
            InitializeComponent();
            DataContext = new ItemsControlBindingTestViewModel();
        }
     }
}

您可以看到我只是将 View 的 DataContext 属性设置为 ItemsControlBindingTestViewModel 的新实例。

还有 ItemsControlBindingTestViewModel 的代码:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Controls;

namespace ItemsControlBindingTest.ViewModels
{
    public class ItemsControlBindingTestViewModel : MVVM.ViewModelBase
    {
        private ObservableCollection<Button> buttonList;
        public ObservableCollection<Button> ButtonList
        {
            get { return buttonList; }
            set
            {
                buttonList = value;
                NotifyPropertyChanged(() => ButtonList);
            }
        }

        public ItemsControlBindingTestViewModel()
        {
            List<Button> tempList = new List<Button>();
            tempList.Add(new Button { Content = "Button 1" });
            tempList.Add(new Button { Content = "Button 2" });
            tempList.Add(new Button { Content = "Button 3" });
            ButtonList = new ObservableCollection<Button>(tempList);
        }
    }
}

我们在这里所做的只是向 ButtonList 属性添加三个按钮。

现在,当我显示此视图时,我只看到在 XAML 中最后声明的 ItemsControl 中呈现的按钮:

如果我在两个 ItemsControls 上切换分配的列值:

<ItemsControl Grid.Column="1" Grid.Row="1" ItemsSource="{Binding ButtonList}"/>
<ItemsControl Grid.Column="0" Grid.Row="1" ItemsSource="{Binding ButtonList}"/>

那么第0列(左边)的ItemsControl会渲染内容,右边的ItemsControl会保持空白:

查看 Snoop 中的元素会产生一些有趣的信息:

ItemsControls 的 ItemsSource 属性都正确反映了与 ButtonList 的绑定。

其实我可以深入研究这个ItemsSource,看到ButtonList中的三个按钮:

最后声明的 ItemsControl 还显示了一个有效的 ItemsSource 属性:

我也可以深入研究这个 ItemsSource 并查看 ButtonList 中的三个按钮:

Snoop 还显示最后声明的 ItemsControl 的 StackPanel 有子项:

虽然第一个声明的 ItemsControl 的 StackPanel 没有子级:

我在这里遗漏了什么,还是这是 WPF 中的错误?

【问题讨论】:

    标签: c# wpf xaml mvvm


    【解决方案1】:

    如果ButtonSystem.Windows.Controls.Button,则行为正常。 Button(与任何其他视觉对象一样)只能有一个父级。当最后一个项目控件呈现一个项目(按钮)时,该项目与前一个父项分离并附加到下一个。

    事实上,这是一个非常糟糕的主意 - 在视图模型中使用视觉效果。
    此外,在这种情况下,视图模型的概念失去了意义。如果要在视图中生成按钮,请为项目控制设置适当的项目模板,并将数据项(不是视觉对象!)保存在视图模型的 ObservableCollection 中。

    【讨论】:

    • 谢谢,丹尼斯!确实是最后一个声明其子元素的元素导致第一个“丢失”其子元素。我已经修改了我的数据结构,以便创建一个 ObservableCollection,绑定到这个集合,然后在 DataTemplate 中构建我的按钮。像冠军一样工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 2016-10-11
    • 2015-03-19
    • 2010-12-16
    • 1970-01-01
    • 2015-11-25
    相关资源
    最近更新 更多