Reputation: 709
I come from How to use custom styles to bind with custom command? Here's my situation. I have a custom TabControl. And the ItemsSource is in a ViewModel.[Header and Content]. Now the Content is just simple strings.
public ViewModel()
{
TabItems = new ObservableCollection<TabData>();
//dummy data
TabItems.Add(new TabData() { Header = "Tab 1", Content = "Tab content 1" });
But I'd like to make the Content to be some other controls. To say a Grid with Textbox and Treeview inside.
What's the ideal way to do this these kind of bindings?
I am thinking about create a userControl to hold the grid with textbox and treeview inside, and in the original ViewModel, I can write Header = "Tab 1", Content = new UserControl()
Upvotes: 2
Views: 237
Reputation: 13669
Here is how you can implement view model for nested components
I'll demo the same by displaying a user control in Tab 2 via MVVM
so let's start by defining a view model class
public class Tab2ViewModel : ViewModelBase
{
public Tab2ViewModel()
{
TabCommand = new SimpleCommand(OnTabCommand);
}
public ICommand TabCommand { get; private set; }
private void OnTabCommand(object obj)
{
TabText = "Button was clicked";
}
private string _tabText;
public string TabText
{
get { return _tabText; }
set
{
_tabText = value;
RaisePropertyChanged();
}
}
}
ViewModelBase
class in the code above is an implementation of INotifyPropertyChanged
providing a method RaisePropertyChanged
to notify the property changes
lets define a view for this view model
<UserControl x:Class="test_tab_control5.Views.Tab2View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel>
<TextBlock Text="Tab 1"
FontWeight="Bold" Margin="10"/>
<TextBlock Text="{Binding TabText,FallbackValue=tab text}" Margin="10"/>
<Button Command="{Binding TabCommand}"
Content="Click me" HorizontalAlignment="Center"/>
</StackPanel>
</UserControl>
now lets define a data template for the same
<DataTemplate DataType="{x:Type vm:Tab2ViewModel}">
<vw:Tab2View />
</DataTemplate>
this is how you can define a template for the view models, in this case I a defining for Tab2ViewModel
. in code above the namespaces defined as xmlns:vm="clr-namespace:test_tab_control5.ViewModels"
& xmlns:vw="clr-namespace:test_tab_control5.Views"
finally the usage
TabItems.Add(new TabData() { Header = "Tab 2", Content = new Tab2ViewModel() });
note that I am setting the content as Tab2ViewModel
instead of any user control, this allows me implement a loose coupling between the view model and the view
and as a result WPF will resolve the user control as the template for the Tab2ViewModel
result
here is a full working sample for the above code: MVVM TabControl.zip
MD5 Checksum: 4BA61028B5179AA884ECAC21D69A816A
this sample is based on the sample shared in your previous question How to use custom styles to bind with custom command?
With the working sample I have also attempted to show couple of ways to define a template and usage of resource dictionaries
Upvotes: 1