wpf 使用 MVVM 将 UserControl 加载到 ItemsControl

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13843824/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 06:35:09  来源:igfitidea点击:

Loading UserControl to ItemsControl with MVVM

wpfmvvmuser-controlsitemscontrol

提问by PitAttack76

I have a UserControl which I would like to load multiple times on my MainWindow. For this I use an 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>

My UserControl is bound by a ViewModel. My MainWindow also has a ViewModel. In the MainWindowViewModel I have an OberservableCollection dependency property which houlds a list of my UserControlViewModels. In the constructor of the MainWindowViewModel I add some UserControlViewModels to the List.

我的 UserControl 受 ViewModel 约束。我的 MainWindow 也有一个 ViewModel。在 MainWindowViewModel 我有一个 OberservableCollection 依赖属性,它包含我的 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); }
}

Now for some reason it loads 3 times an empty usercontrol and NOT the ones in the FtpControlList property withe the property set to 'View 1, View 2 and View 3'. How can I make sure that the UserControls from the list are loaded and not empty ones?

现在由于某种原因,它加载了 3 次空用户控件,而不是 FtpControlList 属性中的那些,并且属性设置为“视图 1、视图 2 和视图 3”。如何确保加载了列表中的 UserControl 而不是空的?

Part of the UserControlViewModel:

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

It will probably be something stupid but I can't seem to find it. The datacontext for MainWindow and the UserControl are bound to it's Viewmodel.

这可能是愚蠢的,但我似乎无法找到它。MainWindow 和 UserControl 的数据上下文绑定到它的 Viewmodel。

EDIT: BackupControl datacontext set to BackupControlViewModel (to answer Rachel's question)

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

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

回答by Rachel

You are overwriting the DataContextof your UserControlby setting it in the constructor of your UserControlafter calling InitializeComponent();

您通过在调用后的构造函数中设置它来覆盖DataContextUserControlUserControlInitializeComponent();

By default, the ItemsControlwill create an ItemTemplatefor each item in the collection, and set it's DataContextto the item from the ItemsSource. The end result will be three new my:BackUpControlobjects, with the DataContextbehind those objects bound to the BackUpControlViewModelfrom ItemsControl.ItemsSource

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

Remove the line this.DataContext = new BackUpControlViewModel();from your UserControl's constructor, and it should work like you expect

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

回答by user303754

The issue might be that your viewmodel has dependency properties. Normally you would just make your viewmodel implement INotifyPropertyChangedand the properties would be regular (not dependency properties). Unless you have a specific requirement for them to be DPs I'd switch them over.

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

回答by Arthur Nunes

Change :

改变 :

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

To:

到:

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