使用MVVM将UserControl加载到ItemsControl中

3

我有一个用户控件,我想在我的主窗口上加载多次。 为此,我使用了一个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>

我的用户控件通过 ViewModel 进行绑定。我的主窗口(MainWindow)也有一个 ViewModel。在 MainWindowViewModel 中,我有一个 Observable Collection 依赖属性,它保存了我的 UserControlViewModel 列表。在 MainWindowViewModel 的构造函数中,我向该列表中添加了一些 UserControlViewModel。

    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 次空的用户控件而不是 FtpControlList 属性中设置为 'View 1, View 2 和 View 3' 的用户控件。我该如何确保从列表中加载 UserControls 而不是空的 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的数据上下文绑定到它的ViewModel。

编辑:BackupControl数据上下文设置为BackupControlViewModel(回答Rachel的问题)

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

BackUpControlViewModel 实际上是一个 UserControl 吗?或者你在 my:BackUpControlUserControl 中设置了 DataContext 吗?根据你提供的代码,WPF 应该会加载三个空白的 my:BackUpControl 对象,并将这些对象后面的 DataContext 绑定到 BackUpControlViewModel - Rachel
@Rachel。我编辑了我的帖子,并为BackupUserControl添加了datacontext设置。你说的是正确的,它加载了3个空白用户控件。但是为什么它不加载我在MainViewModel中添加到FtpControlList中的3个用户控件视图模型?请参见public MainWindowViewModel() { FtpControlList = new ObservableCollection<BackUpControlViewModel>(); FtpControlList.Add(new BackUpControlViewModel("View 1")); FtpControlList.Add(new BackUpControlViewModel("View 2")); FtpControlList.Add(new BackUpControlViewModel("View 3")); } - PitAttack76
3个回答

6

您正在通过在UserControl的构造函数中设置它来覆盖UserControlDataContext,并在调用InitializeComponent();后进行设置。

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

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


谢谢,解决了。我知道问题出在绑定上,但是一直看不出来是什么。有时候这让我感到困惑 :) 你真棒! - PitAttack76

0

更改:

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

To:

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

仍然无法工作,仍会加载3个空的用户控件视图模型,而不是我添加到MainWindowViewModel上的FtpControlList中的视图模型。 - PitAttack76
它至少能加载BackUpControl实例吗?您需要确定问题是模板未应用还是BackUpControls中的某些绑定未被正确评估。如果后者,我们需要检查您的BackUpControl xaml以查看其应该如何呈现。 - Arthur Nunes

0
问题可能是您的视图模型具有依赖属性。通常,您只需使您的视图模型实现INotifyPropertyChanged,并且属性将是常规属性(而不是依赖属性)。除非您有特定要求使它们成为DP,否则我会将它们切换过来。

不对,那不是问题所在。我将GroupBoxHeader属性更改为NotifyChanged属性,但结果仍然相同.. - PitAttack76
你的输出中是否有任何绑定错误?例如“绑定错误:属性blah不存在……” - user303754
是的,我的所有属性都出现了以下错误:System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=GroupBoxHeader; DataItem=null; target element is 'GroupBox' (Name='groupBox1'); target property is 'Header' (type 'Object')。但是如何解决这个问题呢?我在绑定方面肯定做错了什么。 - PitAttack76

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接