So as mentioned in an earlier question I asked WPF Data Binding From UserControl I have succesfulyl binded the TabHeader of my Control based off a value inside my UserControls code behind file using DependencyProperty, and acheived a a similar implementation with INotifyPropertyChanged.
However I now need it to work off the value from the UserControls ViewModel. I can succesfully update the UserControl UI using INotifyPropertyChanged but I am unable to bind this value to the TabItem control in the Main Window as it seems to regonise it.
Is this even possibly or am I barking up the wrong tree?
Main Window (TabControl) <---> UserControl <---> ViewModel
MainWindow.xaml
<Grid>
<TabControl Height="250" HorizontalAlignment="Left" Margin="12,26,0,0" Name="tabControl1" VerticalAlignment="Top" Width="479">
<TabControl.Resources>
<Style TargetType="TabItem" x:Key="tab1ItemHeaderStyle" >
<Setter Property="HeaderTemplate" >
<Setter.Value>
<DataTemplate DataType="{x:Type TabItem}">
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Path=Header, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TabItem}}"/>
<Label Content="{Binding Path=SomeFigureVM, ElementName=uc1}"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabItem Style="{StaticResource tab1ItemHeaderStyle}" Header="[Tab 1]" Name="tabItem1">
<vw:UserControl1 x:Name="uc1"></vw:UserControl1>
</TabItem>
</TabControl>
</Grid>
UserControl1.xaml
<Grid>
<Label Height="43" HorizontalAlignment="Left" Margin="69,128,0,0" Name="textBlock" Content="{Binding SomeFigureVM}" VerticalAlignment="Top" Width="100" />
<Button Name="updateSomeFigure" Content="Update.." Click="updateSomeFigure_Click" Width="100" Height="100" Margin="69,12,66,71" />
</Grid>
UserControl1.xaml.cs
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
this.DataContext = new MyViewModel();
}
private void updateSomeFigure_Click(object sender, RoutedEventArgs e)
{
MyViewModel viewmodel = this.DataContext as MyViewModel;
viewmodel.UpdateFigure();
}
}
MyViewModel.cs
public class MyViewModel: INotifyPropertyChanged
{
public MyViewModel()
{
this.SomeFigureVM = 23;
}
private int _someFigure;
public int SomeFigureVM
{
get
{
return _someFigure ;
}
set
{
_someFigure = value;
NotifyPropertyChanged("SomeFigureVM");
}
}
public void UpdateFigure()
{
SomeFigureVM = SomeFigureVM + 1;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
As always, any help is greatly appreciated, I feel like I've been smashing my head against a brick wall on this one!
SomeFigureVM is a property on your MyViewModel
, which is the DataContext
for UserControl1
. You are trying to access SomeFigureVM prperty on UserControl, which doesn't exist.
Change this line:
<Label Content="{Binding Path=SomeFigureVM, ElementName=uc1}"/>
to
<Label Content="{Binding Path=DataContext.SomeFigureVM, ElementName=uc1}"/>
To catch data binding errors like this, run the application in debug mode and watch the output window for any data binding issues. Your original code generates a data binding error like:
System.Windows.Data Error: 40 : BindingExpression path error: 'SomeFigureVM' property not found on 'object' ''UserControl1' (Name='uc1')'. BindingExpression:Path=SomeFigureVM; DataItem='UserControl1' (Name='uc1'); target element is 'Label' (Name=''); target property is 'Content' (type 'Object')