3
votes

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

    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?

Part of the 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.

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

   public partial class BackUpControl : UserControl
  {
    public BackUpControl()
    {
      InitializeComponent();
      this.DataContext = new BackUpControlViewModel();
    }
  }
3
Is BackUpControlViewModel actually a UserControl? Or do you set the DataContext anywhere in the UserControl my:BackUpControl? Based on your code provided, WPF should load you three blank my:BackUpControl objects, with the DataContext behind those objects bound to the BackUpControlViewModelRachel
@Rachel. I've edited my post and added the datacontext setting for the BackupUserControl. What you say is correct, it loads me 3 blank usercontrols. But why doesn't it load my 3 usercontrol viewmodels I add to FtpControlList in the MainViewModel? See 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 Answers

6
votes

You are overwriting the DataContext of your UserControl by setting it in the constructor of your UserControl after calling InitializeComponent();

By default, the ItemsControl will create an ItemTemplate for each item in the collection, and set it's DataContext to the item from the ItemsSource. The end result will be three new my:BackUpControl objects, with the DataContext behind those objects bound to the BackUpControlViewModel from ItemsControl.ItemsSource

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

0
votes

Change :

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

To:

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

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