Bind Dependency property defined in Code-Behind through Xaml for property in DataContext UserControl
I want to use code similar to the one found here. The problem I'm running into is that I would like to expand it to allow the value set in XAML to be used {Binding PropertyOfViewModel}
like this:
<local:TestControl>
<local:TestControl.TestObject>
{Binding PropertyOfViewModel}
</local:TestControl.TestObject>
</local:TestControl>
The problem is that these are errors with "Can not Convert" {Binding PropertyOfViewModel} "". The TestObject property is defined as a dependency property in the code for the view.
If I can get it to work, it will allow me to write code like this in the parent control:
<local:TestControl x:Name="myControl" DataContext="{Binding TCViewModel}" />
This means that in the UserControl I can also bind to commands and other items open in my TCViewModel and the control can be mostly self contained and all the consumer needs is the DataContext property.
change
This is the whole control:
<UserControl x:Class="MyProject.Views.AddClientView"
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"
xmlns:Views="clr-namespace:MyProject.Views"
Background="{StaticResource WindowBackgroundBrush}"
mc:Ignorable="d">
<!-- Comment out from here
<Views:AddClientView>
<Views:AddClientView.RenderTransform>
<ScaleTransform ScaleY="1" />
</Views:AddClientView.RenderTransform>
<Views:AddClientView.IsInAcceptDataMode>
<Binding Path="IsInInputMode"/>
</Views:AddClientView.IsInAcceptDataMode>
<Views:AddClientView.ContentTemplate>
<DataTemplate>
to here -->
<Grid>
<Label
Height="25"
Width="306"
HorizontalAlignment="Left"
Margin="12,12,0,0"
OverridesDefaultStyle="False"
Style="{DynamicResource CalloutLabel}"
VerticalAlignment="Top" Content="Company Name (Name of Organizational Unit)"/>
<TextBox Height="23" Margin="12,41,12,0" VerticalAlignment="Top" TabIndex="1" />
<Button
Style="{DynamicResource LightButton}"
Height="23" Width="75"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,97,12"
TabIndex="4">OK</Button>
<Button
Style="{DynamicResource LightButton}"
Height="23" Width="75"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,12,12"
Command="{Binding Cancel}"
TabIndex="3">Cancel</Button>
<CheckBox Content="Make Groups" Height="16" IsChecked="True" FlowDirection="RightToLeft" Margin="150,79,12,0" VerticalAlignment="Top" TabIndex="2" />
<Rectangle Fill="{DynamicResource HeaderBarFill}" Height="5" Margin="0,0,0,0" Stroke="{x:Null}" VerticalAlignment="Bottom" />
</Grid>
<!-- and here
</DataTemplate>
</Views:AddClientView.ContentTemplate>
</Views:AddClientView>
to here-->
To get it to compile with the suggested code, I had to reorder my xaml, now it simultaneously crashes Visual Studio in design mode and when I run it I get a StackOverflow exception InitializeComponent();
in the view designer.
change 2
This is the code that puts this UserControl on the window:
<Views:AddClientView x:Name="AddClient" VerticalAlignment="Top" DataContext="{Binding AddClientVM}">
</Views:AddClientView>
Interesting: If I remove this code from the window, it runs / compiles OK. If I remove all of the type code <Views:AddClientView...>
from the view, it also works fine. But doesn't do what I want, because I can't bind my DP to the DataContext.
If I change the UserControl to below everything compiles fine, I just lose my code dependency property binding:
<UserControl
x:Class="Mage.Views.AddClientView"
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"
xmlns:Views="clr-namespace:Mage.Views"
Background="{StaticResource WindowBackgroundBrush}"
mc:Ignorable="d" d:DesignWidth="320" d:DesignHeight="145"
x:Name="AddClientV"
MaxHeight="145" MinHeight="145">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Show">
<VisualState.Storyboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.(ScaleTransform.ScaleY)"
Storyboard.TargetName="AddClientV"
From="0"
To="1"
Duration="0:0:1" />
</Storyboard>
</VisualState.Storyboard>
</VisualState>
<VisualState x:Name="Hide">
<VisualState.Storyboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.(ScaleTransform.ScaleY)"
Storyboard.TargetName="AddClientV"
From="1"
To="0"
Duration="0:0:1" />
</Storyboard>
</VisualState.Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Views:AddClientView>
<Views:AddClientView.RenderTransform>
<ScaleTransform ScaleY="1" />
</Views:AddClientView.RenderTransform>
<Views:AddClientView.IsInAcceptDataMode>
<Binding Path="IsInInputMode"/>
</Views:AddClientView.IsInAcceptDataMode>
<Views:AddClientView.ContentTemplate>
<DataTemplate>
<Grid>
<Label
Height="25"
Width="306"
HorizontalAlignment="Left"
Margin="12,12,0,0"
OverridesDefaultStyle="False"
Style="{DynamicResource CalloutLabel}"
VerticalAlignment="Top" Content="Company Name (Name of Organizational Unit)"/>
<TextBox Height="23" Margin="12,41,12,0" VerticalAlignment="Top" TabIndex="1" />
<Button
Style="{DynamicResource LightButton}"
Height="23" Width="75"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,97,12"
TabIndex="4">OK</Button>
<Button
Style="{DynamicResource LightButton}"
Height="23" Width="75"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,12,12"
Command="{Binding Cancel}"
TabIndex="3">Cancel</Button>
<CheckBox Content="Make Groups" Height="16" IsChecked="True" FlowDirection="RightToLeft" Margin="150,79,12,0" VerticalAlignment="Top" TabIndex="2" />
<Rectangle Fill="{DynamicResource HeaderBarFill}" Height="5" Margin="0,0,0,0" Stroke="{x:Null}" VerticalAlignment="Bottom" />
</Grid>
</DataTemplate>
</Views:AddClientView.ContentTemplate>
</Views:AddClientView>
</UserControl>
Code Dependency property:
public bool IsInAcceptDataMode
{
get { return (bool)GetValue(IsInAcceptDataModeProperty); }
set
{
SetValue(IsInAcceptDataModeProperty, value);
if (value)
{
VisualStateManager.GoToState(this, "Show", false);
}
else
{
VisualStateManager.GoToState(this, "Hide", false);
}
}
}
public static readonly DependencyProperty IsInAcceptDataModeProperty =
DependencyProperty.Register("IsInAcceptDataMode", typeof(bool), typeof(AddClientView), new UIPropertyMetadata(false, null));
change 3
So, I was informed that there are XAML based binding issues, I tried to translate the code into code and I still can't get it to work. So, I'm looking at this point for a coding-based way of binding my DependencyProperty to an element in the ViewModel that is specified in the DataContext of my UserControl.
source to share
If I understood everything correctly, then you need a standard MVVM script and standard bindings.
You can do it like this:
<local:TestControl TestObject="{Binding PropertyOfViewModel}">
</local:TestControl>
Or like this:
<local:TestControl>
<local:TestControl.TestObject>
<Binding Path="PropertyOfViewModel"/>
</local:TestControl.TestObject>
</local:TestControl>
Update: In response to the code of yours UserControl
you provided ...
What you are doing is placing the control inside itself, which will obviously give you a StackOverflow exception. You don't need to define ContentTemplate
internally UserControl
. You can simply place content directly as a child:
<UserControl
x:Class="Mage.Views.AddClientView"
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"
xmlns:Views="clr-namespace:Mage.Views"
Background="{StaticResource WindowBackgroundBrush}"
mc:Ignorable="d" d:DesignWidth="320" d:DesignHeight="145"
x:Name="AddClientV"
MaxHeight="145" MinHeight="145">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Show">
<VisualState.Storyboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.(ScaleTransform.ScaleY)"
Storyboard.TargetName="AddClientV"
From="0"
To="1"
Duration="0:0:1" />
</Storyboard>
</VisualState.Storyboard>
</VisualState>
<VisualState x:Name="Hide">
<VisualState.Storyboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.(ScaleTransform.ScaleY)"
Storyboard.TargetName="AddClientV"
From="1"
To="0"
Duration="0:0:1" />
</Storyboard>
</VisualState.Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Views:AddClientView.RenderTransform>
<ScaleTransform ScaleY="1" />
</Views:AddClientView.RenderTransform>
<Views:AddClientView.IsInAcceptDataMode>
<Binding Path="IsInInputMode"/>
</Views:AddClientView.IsInAcceptDataMode>
<Grid>
<Label
Height="25"
Width="306"
HorizontalAlignment="Left"
Margin="12,12,0,0"
OverridesDefaultStyle="False"
Style="{DynamicResource CalloutLabel}"
VerticalAlignment="Top" Content="Company Name (Name of Organizational Unit)"/>
<TextBox Height="23" Margin="12,41,12,0" VerticalAlignment="Top" TabIndex="1" />
<Button
Style="{DynamicResource LightButton}"
Height="23" Width="75"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,97,12"
TabIndex="4">OK</Button>
<Button
Style="{DynamicResource LightButton}"
Height="23" Width="75"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,12,12"
Command="{Binding Cancel}"
TabIndex="3">Cancel</Button>
<CheckBox Content="Make Groups" Height="16" IsChecked="True" FlowDirection="RightToLeft" Margin="150,79,12,0" VerticalAlignment="Top" TabIndex="2" />
<Rectangle Fill="{DynamicResource HeaderBarFill}" Height="5" Margin="0,0,0,0" Stroke="{x:Null}" VerticalAlignment="Bottom" />
</Grid>
</UserControl>
source to share