I'm creating an MVVM application which has two view models, RegisterUserViewModel and UserViewModel. The "RegisterUserViewModel" has a public property which is a collection of "UserViewModel", like the code shown below
public class RegisterUserViewModel : ViewModelBase
{
public ObservableCollection<UserViewModel> Users { get; }
public ObservableCollection<string> UsersFromAD { get; }
}
public class UserViewModel : ViewModelBase
{
public string Name { get; set; }
}
The "RegisterUserViewModel" class also has a "UsersFromAD" property which is populated with the names of users obtained from Active Directory.
My problem lies in data binding from within my views.
I have a MainWindow view which separates its window in two areas (left and right): The area on the left has a list of available commands, and the area on the right has a tab control. The commands on the left are used to open new tabs on the tab control. The TabControl's ItemsSource property is bound to a collection of "ViewModelBase" classes. Each opened tab in the TabControl is automatically bound to a specific view due to DataTemplate bindings, depending on the type of class that is being opened.
Let me be more clear:
1) I have a command on the left that adds a new instance of "RegisterUserViewModel" to the "ObservableCollection" to which the TabControl's ItemsSource property is bound.
2) The MainWindow.xaml file has a section which specifies a DataTemplate that binds a specific view to RegisterUserViewModel, as shown in the code below:
<Window.Resources>
<ResourceDictionary>
<DataTemplate DataType={x:Type ViewModel:RegisterUserViewModel}">
<View:RegisterUserView />
</DataTemplate>
<ResourceDictionary>
<Window.Resources>
3) By doing this, WPF automatically sets the DataContext of my RegisterUserView to my RegisterUserViewModel.
Now, I have added a DataGrid control to my RegisterUserView with its ItemsSource set to my UserViewModel collection (Users). Everything works fine, and users added to the collection show up on the DataGrid.
However, what I want is for the "Name" column on the datagrid to use a DataGridComboBoxColumn, with its ItemsSource property set to the "UsersFromAD" property which lies on my "RegisterUserViewModel" class.
For that, I used the following xaml:
<DataGridComboBoxColumn ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ViewModel:RegisterUserViewModel}}, Path=UsersFromAD}"
SelectedValueBinding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ViewModel:UserViewModel}}, Path=Name}"
/>
However, that does not work. Whenever I run the application, I get the following from the Output Window:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='TestApplication.ViewModel.RegisterUserViewModel', AncestorLevel='1''. BindingExpression:Path=UsersFromAD; DataItem=null; target element is 'DataGridComboBoxColumn' (HashCode=24004376); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='TestApplication.ViewModel.UserViewModel', AncestorLevel='1''. BindingExpression:Path=Name; DataItem=null; target element is 'TextBlockComboBox' (Name=''); target property is 'SelectedValue' (type 'Object')
Can anyone help me with setting these bindings correctly?