Is there something equivalent to TemplateBinding outside of a ControlTemplate? - c#

I'm new to the styling part of WPF. What I want to do is to get the value of an attached property in a setter, e.g.:
<Trigger Property="SomeProperty" Value="SomeValue">
<Setter Property="SomeProperty"
Value="(My attached property, let's say lcl:MyClass.MyString)"/>
</Trigger>
I know that you can get something to this effect using a {TemplateBinding lcl:MyClass.MyString} in a ControlTemplate. My question is: can you do this in a style, without using a ControlTemplate?

You can try to use:
<Setter Property="SomeProperty" Value="{Binding Path=(lcl:MyClass.MyString), RelativeSource={RelativeSource self}}"/>
if your attached property applies to the element as your style. If not, you can use RelativeSource or ElementName to find the appropriate element.
I am not sure how you have done that since your code lacks of details. Below code works:
<UserControl.Resources>
<Style x:Key="LabelStyle" TargetType="{x:Type Label}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Content"
Value="{Binding Path=(TestWebBrowser:AttachP.ValueEditorState), RelativeSource={RelativeSource self}}"/>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<StackPanel>
<Label x:Name="label" TestWebBrowser:AttachP.ValueEditorState="HelloWorld" Style="{StaticResource LabelStyle}"/>
<Button Content="Disable Label" Click="Button_Click"/>
</StackPanel>
Button's click event handler will set Label's IsEnabled to false to trigger the trigger. And note that you have to use Path= with parenthesis in the binding.

Related

XAML/C# Hiding a TextBlock if the bound value is empty

in my WPF application I have a listview that only appears if a bound item has an values, this works like so
<ListView Grid.Row="1" Grid.Column="1" Margin="0,5,0,20" BorderThickness="0"
ItemContainerStyle="{StaticResource SelectionlessListViewItemStyle}"
ItemsSource="{Binding MissingAssets}">
<ListView.Style>
<Style TargetType="ListView">
<Style.Triggers>
<Trigger Property="HasItems" Value="False">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListView.Style>
So this will only display the listview if MissingAssets has any values and works fine, above that I wanted a textblock as a header to just say "The following assets could not be found", and I want to hide this text of course if this listview is hidden too, I tried implementing it like this
<TextBlock Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" FontWeight="Bold" Text="The following assets could not be found">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding MissingAssets}" Value="">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
But for some reason it won't hide even if MissingAssets is empty, I've tried using several different things in Value="" but nothing gets it to work. Is there a property or something I'm forgetting to set?
Thanks
You have many options here. The simplest should be to bind the TextBlock.Visibility to the ListView.Visibilty:
<StackPanel>
<TextBlock Visibility="{Binding Elementname="MissingAssetsListView", Path="Visbibility" />
<ListView x:Name="MissingAssetsListView" />
</StackPanel>
Found a workaround, I created a new string property in my C# code that remains blank unless missing assents are found, if they are found I populate the string and bind that string to a label in my XAML, so if the string is empty then there will be no visible label on the UI

Force focus on control via xaml style

I have a treeview and a listbox.
I want to specify on the style trigger-setter option that, when the listbox visibility is Hidden the focus have to return on the treeview.
Is it possibile to condition an user control focus on the state of another user control?
something like
<Style TargetType="{x:Type TreeView}">
<Style.Triggers>
<Trigger Property="Visibility" Value="Hidden">
<Setter Property="IsFocus" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
Yes it is, see the example here
FOR CHILDREN IN CONTAINERS
<StackPanel FocusManager.FocusedElement="{Binding ElementName=lol}">
<TextBox x:Name="lol"/>
<TextBox x:Name="lul"/>
</StackPanel>
FOR SELF
<TextBox FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"/>

How to Change ContentControl `s Content on Toggle Button IsChecked Proprrty

Currently i am working on Changing the Content ( as image) of a container on toggle button IsChecked Proprty.
So i thought ContentControl would be a nice choice for a container. But i am not able to figure out how to achieve the result.
I created a resource of images in windows.resource
<Image Source="Resources/Desert.jpg" x:Key="image1"/>
<Image Source="Resources/Koala.jpg" x:Key="image2"/>
<Image Source="Resources/Lighthouse.jpg" x:Key="image3"/>
<Image Source="Resources/Chrysanthemum.jpg" x:Key="image4"/>
So i thought to Use the above resource to change the Content Property of a ContentControl by changing the ControlTemplate proprty by using Triggers where SourceName as (ToggleButton) and TargetName as (ContentControl) but its not working
SO how can I change the content of a ContentControl on toggleButton Ischeck property.
Edit
<ContentControl BorderBrush="Black" Name="cc">
<ControlTemplate>
<ControlTemplate.Triggers>
<Trigger SourceName="ToggleButton" Property="IsChecked" Value="True">
<Setter TargetName="cc" Property="Content" Value="{StaticResource image1}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ContentControl>
I just tried as i have no idea how to do it.....
Any help are welcomed
You seem to have over complicated the situation unnecessarily. You can just use an Image control rather than a ContentControl. To alternate between two Images, you can simply do this with a DataTrigger:
<Image Source="Resources/Desert.jpg" x:Key="image1"/>
<StackPanel>
<ToggleButton Name="Button" Content="Change Image" Margin="10" />
<Image Margin="10,0,10,10">
<Image.Style>
<Style>
<Setter Property="Image.Source"
Value="/YourAppName;component/Resources/Desert.jpg" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=Button}"
Value="True">
<Setter Property="Image.Source"
Value="/YourAppName;component/Images/Resources/Koala.jpg" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>

WPF Style DataTrigger with binding to DataContext not working

I have a TextBox with a style that has a DataTrigger which changes the text, like this:
<Grid>
<TextBlock Text="Foo">
<TextBlock.Style>
<Style BasedOn="{StaticResource TextStyle}" TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding MyBool}" Value="True">
<Setter Property="Text" Value="Bar"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
But it's not working, the text never changes to "Bar". I have tested using another TextBlock with Text="{Binding MyBool}" and this text changes from "False" to "True". Snoop reveals no errors that I can see and there is nothing in the output.
This question may seem like a duplicate of WPF Trigger binding to MVVM property, but my code does not seem different from the accepted answer there (http://www.thejoyofcode.com/Help_Why_cant_I_use_DataTriggers_with_controls_in_WPF.aspx, section "Using a style") in any relevant way. And using a DataTemplate as suggested in the actual answer seems wrong since I only want this to apply to a single TextBlock, but if it is correct, I'm not sure how to write a DataTemplate for this...
EDIT:
This is what the property I'm binding to looks like:
public bool MyBool
{
get { return _myBool; }
set
{
if (_myBool== value)
return;
_myBool= value;
NotifyPropertyChanged();
}
}
private bool _myBool;
Dependency Properties can be set from many different places; inline, animations, coercion, triggers, etc. As such a Dependency Property Value Precedence list was created and this dictates which changes override which other changes. Because of this order of precedence, we can't use a Trigger to update a property that is explicitly set inline in your XAML. Try this instead:
<Grid>
<TextBlock>
<TextBlock.Style>
<Style BasedOn="{StaticResource TextStyle}" TargetType="TextBlock">
<!-- define your default value here -->
<Setter Property="Text" Value="Foo" />
<Style.Triggers>
<DataTrigger Binding="{Binding MyBool}" Value="True">
<!-- define your triggered value here -->
<Setter Property="Text" Value="Bar" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>

How to approach item count checker

I'm trying to create a trigger to disable the combobox drop down button if there are no items. This is the XAML code I've tried so far, however I am unsure of how to detect whether there are no items contained in the ComboBox, and how to disable the button which drops down the list specifically.
<Style TargetType="ComboBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<ControlTemplate.Triggers>
<Trigger Property="Items.Count" Value="0">
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This worked for me:
<ComboBox IsEnabled="{Binding RelativeSource=
{RelativeSource Mode=Self}, Path=ItemsSource.Count}"/>
Assuming whatever you have bound to your ItemsSource property has a count method (it worked for ObservableCollection). It's actually kind of interesting that count being 0 resolves to false in xaml, however this wouldn't be the case in C#.
You can add it to a style if you need to add it to a control programatically
<Style TargetType="ComboBox" x:Key="ComboStyle">
<Setter Property="IsEnabled" Value="{Binding RelativeSource=
{RelativeSource Mode=Self}, Path=ItemsSource.Count}"/>
</Style>
ComboBox cbo = new ComboBox();
cbo.ItemsSource = MyData;
cbo.Style = Resources["ComboStyle"] as Style;

Categories

Resources