使用MVVM将UserControl加载到ItemsControl

时间:2012-12-12 16:08:45

标签: wpf mvvm user-controls itemscontrol

我有一个UserControl,我想在我的MainWindow上多次加载。 为此,我使用ItemsControl

    <ItemsControl Grid.Row="1"
              ItemsSource="{Binding FtpControlList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <WrapPanel Orientation="Horizontal"
                 IsItemsHost="True" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  <ItemsControl.ItemTemplate>
    <DataTemplate DataType="{x:Type my:BackUpControl}">
      <my:BackUpControl Margin="5"
                        Width="500" />
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

我的UserControl受ViewModel绑定。我的MainWindow也有一个ViewModel。 在MainWindowViewModel中,我有一个OberservableCollection依赖项属性,该属性需要一个UserControlViewModel列表。在MainWindowViewModel的构造函数中,我将一些UserControlViewModels添加到List。

    public MainWindowViewModel()
{
  FtpControlList = new ObservableCollection<BackUpControlViewModel>();
  FtpControlList.Add(new BackUpControlViewModel("View 1"));
  FtpControlList.Add(new BackUpControlViewModel("View 2"));
  FtpControlList.Add(new BackUpControlViewModel("View 3"));
}

public static readonly DependencyProperty FtpControlListProperty = DependencyProperty.Register("FtpControlList", typeof(ObservableCollection<BackUpControlViewModel>), typeof(MainWindowViewModel));
public ObservableCollection<BackUpControlViewModel> FtpControlList
{
  get { return (ObservableCollection<BackUpControlViewModel>)GetValue(FtpControlListProperty); }
  set { SetValue(FtpControlListProperty, value); }
}

现在由于某种原因,它加载了3次空的usercontrol,而不是FtpControlList属性中的属性设置为“View 1,View 2和View 3”。如何确保列表中的UserControls已加载而不是空的?

UserControlViewModel的一部分:

    // part of the UserControl Viewmodel
    public BackUpControlViewModel()
{
}

public BackUpControlViewModel(string header)
{
  GroupBoxHeader = header;
}

    #region Dependency Properties
public static readonly DependencyProperty GroupBoxHeaderProperty = DependencyProperty.Register("GroupBoxHeader", typeof(string), typeof(BackUpControlViewModel), new UIPropertyMetadata("empty"));
public string GroupBoxHeader
{
  get { return (string)GetValue(GroupBoxHeaderProperty); }
  set { SetValue(GroupBoxHeaderProperty, value); }
}

public static readonly DependencyProperty FtpUrlProperty = DependencyProperty.Register("FtpUrl", typeof(string), typeof(BackUpControlViewModel), new UIPropertyMetadata("ftpurl"));
public string FtpUrl
{
  get { return (string)GetValue(FtpUrlProperty); }
  set { SetValue(FtpUrlProperty, value); }
}

public static readonly DependencyProperty FtpUserProperty = DependencyProperty.Register("FtpUser", typeof(string), typeof(BackUpControlViewModel), new UIPropertyMetadata("ftpUser"));
public string FtpUser
{
  get { return (string)GetValue(FtpUserProperty); }
  set { SetValue(FtpUserProperty, value); }
}
#endregion

它可能是愚蠢的东西,但我似乎无法找到它。 MainWindow和UserControl的datacontext绑定到它的Viewmodel。

编辑:BackupControl datacontext设置为BackupControlViewModel(回答Rachel的问题)

   public partial class BackUpControl : UserControl
  {
    public BackUpControl()
    {
      InitializeComponent();
      this.DataContext = new BackUpControlViewModel();
    }
  }

3 个答案:

答案 0 :(得分:6)

您在调用DataContext

后,在UserControl的构造函数中设置UserControl,覆盖了InitializeComponent(); ItemsControl

默认情况下,ItemTemplate会为集合中的每个项目创建DataContext,并将ItemsSource设置为my:BackUpControl中的项目。最终结果将是三个新的DataContext个对象,这些对象后面的BackUpControlViewModel绑定到ItemsControl.ItemsSource的{​​{1}}

从UserControl的构造函数中删除行this.DataContext = new BackUpControlViewModel();,它应该像您期望的那样工作

答案 1 :(得分:0)

问题可能是您的viewmodel具有依赖项属性。通常,您只需使您的viewmodel实现INotifyPropertyChanged,并且属性将是常规的(不是依赖属性)。除非你有特殊要求将它们作为DP,否则我会将它们切换。

答案 2 :(得分:0)

更改:

<DataTemplate DataType="{x:Type my:BackUpControl}">

要:

<DataTemplate DataType="{x:Type my:BackUpControlViewModel}">