Reputation: 4356
I have View with a Rectangle and depending on a boolean variable I want to set the Fill to a specific brush. For this I have added a DependencyProperty to the ViewModel.
public static readonly DependencyProperty FalseColorProperty = DependencyProperty.Register(
"FalseColor",
typeof(Brush),
typeof(BooleanRectangleView),
new FrameworkPropertyMetadata(Application.Current.FindResource("LightGreyBrush"), FrameworkPropertyMetadataOptions.AffectsRender));
public Brush FalseColor
{
get { return (Brush)GetValue(FalseColorProperty); }
set { SetValue(FalseColorProperty, value); }
}
In the View, I added a style to the rectangle with the following Trigger
<DataTrigger Binding="{Binding DataContext.Model.Variable, RelativeSource={RelativeSource AncestorType=UserControl}}" Value="false">
<Setter Property="Fill" Value="{Binding DataContext.FalseColor, RelativeSource={RelativeSource AncestorType=UserControl}}" />
</DataTrigger>
Since I have the DependencyProperty in the ViewModel, I don't know how to set it when creating the UserControl. For example, the following does not work
<BooleanRectangleView FalseColor="..."/>
Also, when I am running the program, I get an exception in the constructor of the ViewModel:
The default type does not match the type of the property
FalseColor
(translated from German)
EDIT:
When I cast the FindResource to Brush I get a new exception:
The default value for the property
FalseColor
cannot be bound to a specific thread
I guess that has something to do with FindResource not necessarily being called from the dispatcher thread?
Upvotes: 1
Views: 1045
Reputation: 2521
I don't understand your structure here: You tell that FalseColorProperty is in the ViewModel layer but the class is called BooleanRectangleView which should probably be a name for a View class (UserControl or something like that).
In your case you'll have this DP in your View in addition to a bool named IsVariableTrue for example.
In your ViewModel you'll have the Variable property which makes the Variable property from your Model accessible.
In the BooleanRectangleView XAMl you'll have a Style:
<Rectangle>
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="{Binding RelativeSource={RelativeSource Self}, Path=Fill}"/> <!-- Binding to the Rectangle Fill property -->
<Style.Triggers>
<DataTrigger Property="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type BooleanRectangleView}}, Path=IsVariableTrue}" Value="False">
<Setter Property="Fill" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type BooleanRectangleView}}, Path=FalseColor}"/> <!-- Binding to the DP in the View -->
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
...
</Rectangle>
In the XAML that uses your BooleanRectangleView:
<BooleanRectangleView IsVariableTrue="{Binding Variable}"/> <!-- Binding to the ViewModel -->
On Your DP declaration:
public static readonly DependencyProperty FalseColorProperty = DependencyProperty.Register(
"FalseColor",
typeof(Brush),
typeof(BooleanRectangleView),
new FrameworkPropertyMetadata(
Brush.Red,
FrameworkPropertyMetadataOptions.AffectsRender
)
);
public Brush FalseColor
{
get { return (Brush)GetValue(FalseColorProperty); }
set { SetValue(FalseColorProperty, value); }
}
You'll want to set the DP value in the constructor of your BooleanRectangleView:
public BooleanRectangleView() {
InitializeComponents();
FalseColor = (Brush)Application.Current.FindResource("Infoteam_LightGreyBrush");
}
I'm sure there's a better solution but it should work fine.
Edited
Replaced the TemplateBinding for a Binding with RelativeSource as we're not in a ControlTemplate. Replaced the Trigger with a DataTrigger because the IsVariableTrue doesn't exist in a Rectangle.
Upvotes: 1