baozi
baozi

Reputation: 709

How to bind nested components together Treeview,textbox & treeview?

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

Answers (1)

pushpraj
pushpraj

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

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

Related Questions