WPF Combobox isn't visible in View while using MVVM pattern [duplicate] - wpf

This question already has answers here:
Why does WPF support binding to properties of an object, but not fields?
(2 answers)
Closed 3 years ago.
I create a wpf project using MVVM patern. In View, when I start a project, I haven't seen any items in ComboBoxes and Labels, though I see items in DataContext in ObservableCollection, when debugging.
What could be wrong with Binding in my code?
My XAML code:
<ItemsControl ItemsSource="{Binding Items}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Content="{Binding Name}" Grid.Column="0" Height="26" Width="105" Margin="5,5,0.2,0"/>
<ComboBox ItemsSource="{Binding ComboBoxItems}" Grid.Column="1" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
XAML.cs code:
this.DataContext = new ViewModel();
InitializeComponent();
ViewModel.cs code:
public ObservableCollection<Model> Items;
public ViewModel()
{
Items = new ObservableCollection<Model>();
Items.Add(new Model { Name = "111111" });
Items.Add(new Model { Name = "222222" });
Items.Add(new Model { Name = "444444" });
Items.Add(new Model { Name = "333333" });
}
Model code:
public class Model : INotifyPropertyChanged
{
public ObservableCollection<string> ComboBoxItems;
public Model()
{
ComboBoxItems =new ObservableCollection<string>();
ComboBoxItems.Add("111111");
ComboBoxItems.Add("222222");
ComboBoxItems.Add("444444");
ComboBoxItems.Add("333333");
}
private string _name;
public string Name
{
get { return _name; }
set
{
_name= value;
OnPropertyChanged("Name");
}
}
public void OnPropertyChanged([CallerMemberName]string prop = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
public event PropertyChangedEventHandler PropertyChanged;
}

You need properties for binding to work.
Change your variable
public ObservableCollection<string> ComboBoxItems;
To a property
public ObservableCollection<string> ComboBoxItems {get;set;}
Similarly Items
public ObservableCollection<Model> Items;
To
public ObservableCollection<Model> Items {get;set;}
You might want to make these propfull and raise property changed in the setter.
But properties have getter and setters.
Variables do not, and will not bind.

Related

WPF DataContext inheritance from MainWindow to UserControl

I am a newbie in WPF, I have a problem concern DataContext inheritance from the MainWindow to a UserControl,
which will be attached as a Tabpage to the MainWindow's Tabcontrol.
My code snippets are as follows:
UserControlModel.cs
public class UserControlModel : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged("Name");
}
}
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
ViewModelLocator.cs
public class ViewModelLocator
{
private UserControlModel UserControlModel { get; set; }
public ObservableCollection<UserControlModel> Users { get; set; }
public ViewModelLocator()
{
Users = new ObservableCollection<UserControlModel>
{
new UserControlModel { Name = "Albert" },
new UserControlModel { Name = "Brian" }
};
}
}
MainWindow.xaml
<Window.Resources>
<local:ViewModelLocator x:Key="VMLocator" />
</Window.Resources>
<Grid HorizontalAlignment="Left" Height="330" VerticalAlignment="Top" Width="592">
<Grid HorizontalAlignment="Left" Height="45" Margin="0,330,-1,-45" VerticalAlignment="Top" Width="593">
<Button Content="Button" HorizontalAlignment="Left" Margin="490,5,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
<TabControl HorizontalAlignment="Left" Height="330" VerticalAlignment="Top" Width="592" >
<TabItem x:Name="UserControlTabItem" Header="User Control">
<Grid x:Name="UserControlTabpage" Background="#FFE5E5E5">
<local:UserControl VerticalAlignment="Top" DataContext="{Binding Users, Source={StaticResource VMLocator}}" />
</Grid>
</TabItem>
</TabControl>
</Grid>
I create an instance of ViewModelLocator and bind Users instance to the UserControl in MainWindow.xaml.
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
}
UserControl.xaml
<Grid>
<ListBox x:Name="lbUsers" DisplayMemberPath="???" HorizontalAlignment="Left" Height="250" Margin="30,27,0,0" VerticalAlignment="Top" Width="378"/>
</Grid>
UserControl.xaml.cs
private ObservableCollection<UserControlModel> _users;
public UserControl()
{
InitializeComponent();
_users = ??? How to reference the Users instance created in MainWindow ???
lbUsers.ItemsSource = _users;
}
Actually, I want to show the Name property of UserControlModel in the ListBox. If I am right, UserControl instance is
inherited with a Users instance as the DataContext from MainWindow. How can I reference the Users instance in the code-behind
of UserControl.xaml.cs? I have checked that DataContext in UserControl constructor is null! How come? What is the
correct way/place to test the DataContext in the code-behind?
Also, how to set DisplayMemberPath attribute of the ListBox in UserControl.xaml. Many thanks.
I think you can set or inherit DataContext in XAML of user control like this
UserControl.xaml
<dialogs:Usercontrol DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext}" />
You need to bind the ItemsSource property of the ListBox to the source collection. Since the DataContext of the UserControl is a ObservableCollection<UserControlModel>, you can bind to it directly:
<ListBox x:Name="lbUsers" ItemsSource="{Binding}" DisplayMemberPath="Name" ... />
Also make sure that you don't explicitly set the DataContext of the UserControl anywhere else in your code.
Although you should be able to reference the DataContext once the UserControl has been loaded:
public UserControl()
{
InitializeComponent();
this.Loaded += (s, e) =>
{
_users = DataContext as ObservableCollection<UserControlModel>;
};
}
...there is no need to set the ItemsSource property of the ListBox in the code-behind. You should do this by creating a binding in the XAML.

How to resolve binding path error on grid view SelectedItem property?

I've set up a DataGrid which is bound to an Observable collection of CustomerModel objects. Also I set up properties for each of the fields within that model and a SelectedCustomer property of type MainViewModel in the VM.
But when I select one of the rows from the DataGrid in order to populate the textboxes below, I get a path error on the field properties, FirstName etc:
System.Windows.Data Error: 40 : BindingExpression path error: 'SelectedCustomer' property not found on 'object' ''DataGrid' (Name='customersgrid')'. BindingExpression:Path=SelectedCustomer.FirstName; DataItem='DataGrid' (Name='customersgrid'); target element is 'TextBox' (Name='fNameTbx'); target property is 'Text' (type 'String')
System.Windows.Data Error: 23 : Cannot convert 'MongoDBApp.Models.CustomerModel' from type 'CustomerModel' to type 'MongoDBApp.ViewModels.MainViewModel' for 'en-US' culture with default conversions; consider using Converter property of Binding. NotSupportedException:'System.NotSupportedException: TypeConverter cannot convert from MongoDBApp.Models.CustomerModel.
In order to debug the issue, I checked my data context of the View, which is set to the VM:
private MainViewModel ViewModel { get; set; }
private static ICustomerDataService customerDataService = new CustomerDataService(CustomerRepository.Instance);
public MainView()
{
InitializeComponent();
ViewModel = new MainViewModel(customerDataService);
this.DataContext = ViewModel;
}
I also checked that the public property names matched the binding names on the UI, which they do. I do know that the second error hints that it cannot convert between the DataGrid binding source of type CustomerModel and the SelectedItem property which is of type MainViewModel.
Anyone have an idea how I can debug this further?
An example of the UI XAML and it's binding paths:
<Grid>
<DataGrid x:Name="customersgrid" Grid.RowSpan="3" Grid.Column="1" Grid.ColumnSpan="3" AutoGenerateColumns="False"
ItemsSource="{Binding Customers}" SelectedItem="{Binding SelectedCustomer}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Id}" Header="ID" />
<DataGridTextColumn Binding="{Binding FirstName}" Header="First Name" />
<DataGridTextColumn Binding="{Binding LastName}" Header="Last Name" />
<DataGridTextColumn Binding="{Binding Email}" Header="Email" />
</DataGrid.Columns>
</DataGrid>
<Label Grid.Row="4" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Top" Content="First Name:" />
<TextBox x:Name="fNameTbx" Grid.Row="4" Grid.Column="2" Grid.ColumnSpan="2" Width="120" Height="23"
HorizontalAlignment="Left" VerticalAlignment="Top" TextWrapping="Wrap"
Text="{Binding SelectedCustomer.FirstName, ElementName=customersgrid}" />
</Grid>
And a short version of the MainViewModel:
namespace MongoDBApp.ViewModels
{
class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ICustomerDataService _customerDataService;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public MainViewModel(ICustomerDataService customerDataService)
{
this._customerDataService = customerDataService;
QueryDataFromPersistence();
}
#region Properties
private MainViewModel selectedCustomer;
public MainViewModel SelectedCustomer
{
get { return selectedCustomer; }
set
{
selectedCustomer = value;
RaisePropertyChanged("SelectedCustomer");
}
}
private ObservableCollection<CustomerModel> customers;
public ObservableCollection<CustomerModel> Customers
{
get { return customers; }
set
{
customers = value;
RaisePropertyChanged("Customers");
}
}
private string firstName;
public string FirstName
{
get { return firstName; }
set
{
firstName = value;
RaisePropertyChanged("FirstName");
}
}
#endregion
private void QueryDataFromPersistence()
{
Customers = _customerDataService.GetAllCustomers().ToObservableCollection();
}
}
}
The error is here:
private MainViewModel selectedCustomer;
public MainViewModel SelectedCustomer
{
get
{
return selectedCustomer;
}
set
{
selectedCustomer = value;
RaisePropertyChanged("SelectedCustomer");
}
}
Change the type of selectedCustomer to CustomerModel instead of MainViewModel

WPF DataGrid SelectionChange event doesn't fire when ItemsSourse is being set from UserControl

I have very interesting scenario here, look:
MainWindow XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<TabControl Grid.Row="0"
Grid.Column="0"
SelectionChanged="Selector_OnSelectionChanged">
<TabItem Header="First"/>
<TabItem Header="Second"/>
</TabControl>
<ContentPresenter Grid.Column="1"
Content="{Binding SelectedUserControl}">
</ContentPresenter>
</Grid>
UserControlOne XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<DataGrid Grid.Row="0"
ItemsSource="{Binding DataSource}"
SelectedItem="{Binding SelectedItem}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<Command:EventToCommand Command="{Binding SelectionChangedCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
<Button Grid.Row="1"
Content="SetSource"
Height="50"
Command="{Binding SetSourceCommand}"/>
<Button Grid.Row="2"
Content="RemoveSource"
Height="50"
Command="{Binding RemoveSourceCommand}"/>
</Grid>
UserContolTwo XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Button Grid.Row="0"
Content="SetSource"
Height="50"
Command="{Binding SetSourceCommand}"/>
<Button Grid.Row="1"
Content="RemoveSource"
Command="{Binding RemoveSourceCommand}"
Height="50"/>
</Grid>
CodeBehind:
public class GridItem
{
public String Name { get; set; }
public override string ToString()
{
return Name;
}
}
public partial class Window1 : Window, INotifyPropertyChanged
{
private List<GridItem> _items;
private GridItem _selectedItem;
private List<GridItem> _dataSource;
private readonly List<UserControl> _userControlList;
private UserControl _selectedUserControl;
public UserControl SelectedUserControl
{
get { return _selectedUserControl; }
set
{
_selectedUserControl = value;
RaisePropertyChanged("SelectedUserControl");
}
}
public GridItem SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
RaisePropertyChanged("SelectedItem");
}
}
public List<GridItem> DataSource
{
get { return _dataSource; }
set
{
_dataSource = value;
RaisePropertyChanged("DataSource");
}
}
public Window1()
{
InitializeComponent();
DataContext = this;
_items = new List<GridItem>
{
new GridItem { Name = "Igor" },
new GridItem { Name = "Vasya"},
new GridItem { Name = "Vladlen"}
};
_userControlList = new List<UserControl>
{
new UserControl1(),
new UserControl2()
};
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(String propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion INotifyPropertyChanged
private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
SelectedUserControl = _userControlList[((TabControl)sender).SelectedIndex];
}
#region SetSourceCommand
private RelayCommand<Object> _setSourceCommand;
public RelayCommand<Object> SetSourceCommand
{
get
{
return _setSourceCommand ?? (_setSourceCommand =
new RelayCommand<Object>(SetSourceMethod));
}
}
private void SetSourceMethod(Object obj)
{
DataSource = _items;
SelectedItem = _items.FirstOrDefault();
}
#endregion SetSourceCommand
#region RemoveSourceCommand
private RelayCommand<Object> _removeSourceCommand;
public RelayCommand<Object> RemoveSourceCommand
{
get
{
return _removeSourceCommand ?? (_removeSourceCommand =
new RelayCommand<Object>(RemoveSourceMethod));
}
}
private void RemoveSourceMethod(Object obj)
{
DataSource = null;
}
#endregion RemoveSourceCommand
#region SelectionChangedCommand
private RelayCommand<Object> _selectionChangedCommand;
public RelayCommand<Object> SelectionChangedCommand
{
get
{
return _selectionChangedCommand ?? (_selectionChangedCommand =
new RelayCommand<Object>(SelectionChangedMethod));
}
}
private void SelectionChangedMethod(Object obj)
{
Debug.WriteLine("Event have been rised! Selected item is {0}", ((DataGrid)obj).SelectedItem ?? "NULL");
}
#endregion RemoveSourceCommand
}
I have MainWindow, that contains UserControl. UserControl is being set dinamically, so if you pick up FirstTabItem, then UserControlOne will be loaded and if you pick up SecondTabItem - UserControlTwo will be loaded into ContentPresenter of MainWindow.
If I click button SetSource on FirstTabItem (actually on UserControlOne) - then SelectionChanged event of DataGrid fires as usually. But if I click button SetSource on SecondTabItem (actually on UserControlTwo) - then SelectionChanged event of DataGrid doesn't fire at all. Despite on bouth buttons bound to the same command (SetSourceCommand).
If buttons don't placed on other controls, for example, only on different tabitems of the same TabControl - bouth buttons invokes SelectionChange event. So problem really in markup, in using UserControls.
Has anyone encoutered with that problem? How can I fix it? I don't want invoke eventhandler programmatically.
I posted all the required code here, so you can copy-paste it and try by yourself very quickly. Or I can load example project if someone interested.
Okay so here is the actual problem in your code.
The UserControl1 has a grid in which you have used the SelectedItem Dependency Property. On this specific DP you have a Command SelectionChangedCommand.
In you commands SetSourceCommand and RemoveSourceCommand you are updating SelectedItem of the data grid which fires the SelectionChangedCommand because of the event SelectionChanged.
In your UserControl2 there is no data grid nor any control which fires SelectionChanged event to call SelectionChangedCommand. Hence it is never executed.

DataTemplate disappears when moving items in ObservableCollection

I have a CellTemplate for a column in a ListView. The CellTemplate contains a ComboBox which has an ItemTemplate. Both ItemsSource and SelectedItem is bound to another ViewModel.
The ListView is bound to an ObservableCollection on a ViewModel. Above the ListView there is a toolbar with the buttons to move the selected item up and down. I buttons a bound to and ICommand which will make a Move on the ObservableCollection.
The view is updated fine, but the selected item in the ComboBox is not using the DataTemplate and is just showing the type name.
I found out that everything is working fine if IsEditable = false, but I need this to be true.
I have created a small project that verifies the problem. Perhaps this is an issue in WPF.
Here is XAML:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:WpfApplication3="clr-namespace:WpfApplication3"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type WpfApplication3:Item}">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
<DataTemplate x:Key="cellTemplate">
<ComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" Width="100" IsEditable="true" TextSearch.TextPath="Name"/>
</DataTemplate>
</Window.Resources>
<Grid>
<StackPanel>
<ToolBar>
<Button Content="Add" Command="{Binding AddItemCommand}"/>
<Button Content="Up" Command="{Binding MoveItemUpCommand}" CommandParameter="{Binding ElementName=listView, Path=SelectedItem}"/>
<Button Content="Down" Command="{Binding MoveItemDownCommand}" CommandParameter="{Binding ElementName=listView, Path=SelectedItem}"/>
</ToolBar>
<ListView x:Name="listView" ItemsSource="{Binding Collection}">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" CellTemplate="{StaticResource cellTemplate}"/>
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</Grid>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
public class ViewModel
{
public ICommand AddItemCommand { get; private set; }
public ICommand MoveItemUpCommand { get; private set; }
public ICommand MoveItemDownCommand { get; private set; }
public ObservableCollection<Row> Collection { get; set; }
public ViewModel()
{
Collection = new ObservableCollection<Row>();
AddItemCommand = new RelayCommand(AddItem);
MoveItemUpCommand = new RelayCommand<Row>(MoveItemUp, CanMoveItemUp);
MoveItemDownCommand = new RelayCommand<Row>(MoveItemDown, CanMoveItemDown);
}
private bool CanMoveItemDown(Row arg)
{
if (arg == null)
return false;
return Collection.Last() != arg;
}
private void MoveItemDown(Row obj)
{
var index = Collection.IndexOf(obj);
Collection.Move(index, index + 1);
}
private bool CanMoveItemUp(Row arg)
{
if (arg == null)
return false;
return Collection.First() != arg;
}
private void MoveItemUp(Row row)
{
var index = Collection.IndexOf(row);
Collection.Move(index, index - 1);
}
private void AddItem()
{
Collection.Add(new Row());
}
}
public class Row
{
public Row()
{
Items = new List<Item> { new Item { Name = "Test1" }, new Item { Name = "Test2" } };
}
public List<Item> Items { get; set; }
public Item SelectedItem { get; set; }
}
public class Item
{
public string Name { get; set; }
public int Order { get; set; }
}

DataTemplate inside HierarchicalDataTemplate

I needed to build a custom treeview as a user control. I called it for the sake of the example TreeViewEx :
<UserControl x:Class="WpfApplication4.TreeViewEx"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="root">
<Grid>
<TreeView ItemsSource="{Binding Path=ItemsSource, ElementName=root}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Node : "/>
<ContentControl Content="{Binding Path=AdditionalContent, ElementName=root}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</UserControl>
The idea is to have a fixed part of the content of the ItemTemplate and a customizable part of it.
Of course, I created two dependency properties on the TreeViewEx class :
public partial class TreeViewEx
{
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
"ItemsSource", typeof(IEnumerable), typeof(TreeViewEx));
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty AdditionalContentProperty = DependencyProperty.Register(
"AdditionalContent", typeof(object), typeof(TreeViewEx));
public object AdditionalContent
{
get { return GetValue(AdditionalContentProperty); }
set { SetValue(AdditionalContentProperty, value); }
}
public TreeViewEx()
{
InitializeComponent();
}
}
Having a simple node class like so :
public class Node
{
public string Name { get; set; }
public int Size { get; set; }
public IEnumerable<Node> Children { get; set; }
}
I would feed the treeview. I place an instance of TreeViewEx on the MainWindow of a WPF test project :
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:local="clr-namespace:WpfApplication4">
<Grid>
<local:TreeViewEx x:Name="tree">
<local:TreeViewEx.AdditionalContent>
<TextBlock Text="{Binding Name}"/>
</local:TreeViewEx.AdditionalContent>
</local:TreeViewEx>
</Grid>
</Window>
And finally feed it :
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
var dummyData = new ObservableCollection<Node>
{
new Node
{
Name = "Root",
Size = 3,
Children = new ObservableCollection<Node>
{
new Node{
Name="Child1",
Size=2,
Children = new ObservableCollection<Node>{
new Node{
Name = "Subchild",
Size = 1
}
}
}
}
}
};
tree.ItemsSource = dummyData;
}
}
However it doesn't work as expected namely at first the ContentControl has the data but as I expand the nodes it does not display the ContentControl's content.
I don't really get it.. I should use a DataTemplate or something else?
The problem is that you're setting the content to an instance of a control, and that control can only have one parent. When you expand the tree and it adds it to the second node, it removes it from the first one.
As you suspected, you want to supply a DataTemplate to TreeViewEx instead of a control. You can use a ContentPresenter to instantiate the template at each level of the tree:
Replace the AdditionalContentProperty with:
public static readonly DependencyProperty AdditionalContentTemplateProperty = DependencyProperty.Register(
"AdditionalContentTemplate", typeof(DataTemplate), typeof(TreeViewEx));
public DataTemplate AdditionalContentTemplate
{
get { return (DataTemplate)GetValue(AdditionalContentTemplateProperty); }
set { SetValue(AdditionalContentTemplateProperty, value); }
}
change the HierarchicalDataTemplate in your UserControl's XAML to:
<StackPanel Orientation="Horizontal">
<TextBlock Text="Node : "/>
<ContentPresenter ContentTemplate="{Binding Path=AdditionalContentTemplate, ElementName=root}"/>
</StackPanel>
and change MainWindow to:
<local:TreeViewEx x:Name="tree">
<local:TreeViewEx.AdditionalContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</local:TreeViewEx.AdditionalContentTemplate>
</local:TreeViewEx>

Resources