绑定到VM上相同集合的多个ItemsControl无法正确呈现

时间:2014-01-10 21:32:10

标签: c# wpf xaml mvvm

我遇到了一个我认为可能是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>

你可以看到我只是得到一个带有文本块和两个ItemsControls的网格 - 每个都绑定到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中呈现的按钮:

ItemsControl on right is last-declared in XAML

如果我在两个ItemsControls上切换指定的列值:

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

然后第0列中的ItemsControl(左侧)将呈现内容,右侧的ItemsControl将保持空白:

ItemsControl on left is last-declared in XAML

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

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

Snoop shows first-declared ItemsControl has valid ItemsSource property

事实上,我可以深入研究这个ItemsSource并查看ButtonList中的三个按钮: Snoop shows me the three buttons in ButtonList

最后声明的ItemsControl还显示了一个有效的ItemsSource属性: Last-declared ItemsControl also has valid ItemsSource

我也可以深入研究这个ItemsSource,看看ButtonList中的三个按钮: Last-declared ItemsControl ItemsSource has three buttons

Snoop还显示了最后声明的ItemsControl的StackPanel有子节点: Last-declared ItemsControl's StackPanel has children

虽然第一次声明的ItemsControl的StackPanel没有子节点: First-declared ItemsControl's StackPanel has no children

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

1 个答案:

答案 0 :(得分:3)

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

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