WPF DataGridTextColumn binding and style - c#

here's the deal: styling the DataGridTextColumn's textblock for a datagrid.
I need to format the textblock by it's value, by comparing it from another binded value.
What i want to achieve is something like this:
<Style x:Key="ExpeditionerCellStyle" BasedOn="{StaticResource RightAlignStyle}" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=BEST}" Value="{RelativeSource Mode=Self}">
<Setter Property="Background" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
Which is not possible, because the Value of Datatrigger cannot be a relative source.
So i tried with multibinding
<Style x:Key="ExpeditionerCellStyle" BasedOn="{StaticResource RightAlignStyle}" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource IsValueEqualParameterConverter}">
<Binding Path="BEST" />
<Binding RelativeSource="{RelativeSource Mode=Self}" />
</MultiBinding>
</DataTrigger.Binding>
</DataTrigger>
</Style.Triggers>
</Style>
with no luck: textblock Text property is empty, probably because the style is applied before the actual binding is performed.
I have no more ideas.
Please help me!

I'm not sure if this will work, but I noticed that you forgot to specify the Binding.Path in your MultiConverter example... try this:
<Style x:Key="ExpeditionerCellStyle" BasedOn="{StaticResource RightAlignStyle}" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource IsValueEqualParameterConverter}">
<Binding Path="BEST" />
<Binding Path="Text" RelativeSource="{RelativeSource Mode=Self}" />
</MultiBinding>
</DataTrigger.Binding>
</DataTrigger>
</Style.Triggers>
</Style>

If you only want to change the style of the textblock based on the content of the textblock why not just add a bidning to the textblock background and use a converter to check the content of the text?
In other words bind both the text and the background to the same source and use a converter with the background and in the converter match the content and return the correct background style.
If you need something else leave a comment so we better know what the problem is.

I ended modifying a bit my code.
Instead of relying on the value of the cell, in the field "BEST" i passed the name of the column.
Then using the converter I check
Current textblock (as suggested by #Sheridan) -> DatagridCell -> Column's header
if it match, i change the style on this textblock.
Thanks everyone!!!

Related

Implementing font family from resource in WPF

I am using WPF,C#,XAML
and I wanted to implement a new font family.
the font has been downloaded from the internet and it is a file called:
"LiberationMono-Regular.ttf"
I opened a "Font" folder and add the file into it.
I would like to implement this font into a specific style.
I try to implement it does not work for me.
attaching the code I wrote will appreciate your help
Thanks.
<Window.Resources>
<FontFamily x:Key="DataFont">LiberationMono-Regular.ttf"</FontFamily>
</Window.Resources>
<Style TargetType="syncfusion2:GridCell" x:Key="ComCellData">
<Setter Property="Foreground" Value="{Binding COMPort , Converter={StaticResource CVconverters } }" />
<Setter Property="Background">
<Setter.Value>
<MultiBinding Converter="{StaticResource BookMarkAndSelectedMultiConverter}">
<Binding Path="isBookMarked"></Binding>
<Binding Path="isSelected"></Binding>
</MultiBinding>
</Setter.Value>
</Setter>
<Setter Property="FontFamily" Value="{StaticResource DataFont}"></Setter>
</Style>
You should reference the custom font family by its name:
<FontFamily x:Key="DataFont">/#Liberation Mono</FontFamily>
The above markup assumes that you have added the LiberationMono-Regular.ttf to the root of your project and set its Build Action to Resource.

How to disable validation when TextBox property IsEnabled is false?

I found various answers on StackOverflow, and none of them helped me.
I want turn off validation on TextBox when IsEnabled="false"
What am I missing here?
<TextBox x:Name="idTxtBox">
<!--This is where I tried to disable validation-->
<TextBox.Style>
<Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
<!--I want to disable these validation rules-->
<TextBox.Text>
<Binding Path="ID" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<val:RequiredFieldValidation ValidationStep="RawProposedValue"/>
<val:IsNumberValidation Min="1" Max="250" ValidationStep="ConvertedProposedValue"/>
<val:UniqueIDTag ValidationStep="RawProposedValue"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
<Validation.ErrorTemplate>
<!--........-->
</Validation.ErrorTemplate>
</TextBox>
Without a good Minimal, Complete, and Verifiable code example showing exactly how your code works, and a more specific explanation of what you want the code to do and why your current approach doesn't accomplish that, it's hard to know for sure what answer would serve you best. However, it seems to me that you're on the right track, you're just changing the wrong property.
I would not expect removing the ErrorTemplate value to affect whether validation occurs, just what the user sees. If you want to remove the validation, you should do just that: remove the validation. For example:
<TextBox.Style>
<p:Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<p:Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Text" Value="{Binding ID}"/>
</Trigger>
</p:Style.Triggers>
</p:Style>
</TextBox.Style>
(Ignore the p: namespaceā€¦I just put that in there so that the code formatter Stack Overflow is using won't get side-tracked by the Style element name.)
In other words, the validation is included in the binding. So, when you don't want the validation to occur, change the binding to one without validation (and since the control is disabled, you can omit the UpdateSourceTrigger value as well).

How to Pass multiple parameter in Multivalue Converter Over WPF DataTrigger

I'm having four int Property ProOne, ProTwo, ProThree and ProFour
I have to Implement the Boolean Logic ((ProOne == ProTwo) || (ProThree == ProFour)) in the Multivalue Converter namely VisibilityCheckConverter. Based on the Logic the Multivalue Converter VisibilityCheckConverter returns True or False.
Now I need to pass the four properties to the Converter over DataTrigger, Based on the Value, I have to change the Buttons Visibility to Visible
How does one write the a DataTrigger using Multivalue Converter with multiple parameters?
Sample Piece of XAML Code:
<ControlTemplate.Triggers>
<DataTrigger Property="{Binding , Converter={StaticResource VisibilityCheckConverter,ConverterParameter=ProOne ProTwo ProThree ProFour}}" Value="true">
<Setter TargetName="Button" Property="Visibility" Value="Visible" />
</DataTrigger>
</ControlTemplate.Triggers>
You can do something like this
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource VisibilityCheckConverter}">
<Binding Path="ProOne" />
<Binding Path="ProTwo" />
<Binding Path="ProThree" />
<Binding Path="ProFour" />
</MultiBinding>
</DataTrigger.Binding>
<Setter TargetName="Button" Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>

Change DataTrigger binding reference at runtime

I've a ListView with this DataTrigger attached:
<Style x:Key="HideShowStyle" TargetType="{x:Type ListViewItem}">
<Style.Resources>
<localConverters:ShowHideConverter x:Key="ShowHideConverter" />
</Style.Resources>
<Style.Triggers>
<DataTrigger Value="true">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource showHideConverter}">
<Binding Path="EndingDate" />
<Binding Path="UserName" />
<Binding ElementName="SearchBox" Path="Text" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Value="false">
(...)
</DataTrigger>
</Style.Triggers>
</Style>
I use this in a hardcoded scenario to hide/show some ListItems in the ListView. The binding source is specified in the ElementName tag, and the TextBox referred is declared a few lines before.
Now, I've the necessity to change that Binding at runtime with another field incapsulated in a istantiated class. I've tried to use WPF class instead of XAML, but nothing, I don't have any clue how to obtain this.
I'm open to any advice! :)
var style = (Style)FindResource("HideShowStyle");
var trigger = (DataTrigger)style.Triggers[0];
var multibinding = (MultiBinding)trigger.Binding;
var binding1 = (Binding)multibinding.Bindings[0];
var binding2 = (Binding)multibinding.Bindings[1];
var binding3 = (Binding)multibinding.Bindings[2];
Change bindings at will.

Value Converter not getting called when data changes

I'm working on a user control right now in which I have a path as part of the control. There are 3 possible paths I might want to display based on the values of certain data. To determine which Path I want to use, I have a value converter that takes in the data and returns a number to represent which of the paths I should use.
My first thought was to just use the property changed callback from the two dependency properties I am getting data from, but those callbacks must be static and the XAML code is always non-static.
My second attempt is to now use datatriggers with the value converter described above. Below is the code I have.
<Path x:Name="path" Stretch="Fill" Width="111.75" Height="118.718" Data="F1M205.917,103.0088C189.333,93.8108,170.128,88.9998,150,88.9998C129.873,88.9998,110.584,93.8108,94.167,102.8408L116.1,144.2508L150,208.7178L183.9,144.2508z" Canvas.Left="0" Canvas.Top="0">
<Path.Resources>
<Style TargetType="{x:Type Path}">
<Style.Triggers>
<DataTrigger Value="-1">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource ToleranceRangeTypeChecker}">
<Binding ElementName="UserControl" Path="ToleranceZoneLowerBound" />
<Binding ElementName="UserControl" Path="ToleranceZoneUpperBound" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Data" Value="F1M205.917,103.0088C189.333,93.8108,170.128,88.9998,150,88.9998C129.873,88.9998,110.584,93.8108,94.167,102.8408L116.1,144.2508L150,208.7178L183.9,144.2508z" />
<Setter Property="Width" Value="111.75" />
<Setter Property="Height" Value="118.718" />
<!--<Setter Property="Canvas.SetLeft"-->
</DataTrigger>
<DataTrigger Value="0">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource ToleranceRangeTypeChecker}">
<Binding ElementName="UserControl" Path="ToleranceZoneLowerBound" />
<Binding ElementName="UserControl" Path="ToleranceZoneUpperBound" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Data" Value="F1M150,88.9998C129.873,88.9998,110.584,93.8108,94.167,102.8408L150,208.7178C150,208.7178,150,114.157407529625,150,88.9998z" />
<Setter Property="Width" Value="55.917" />
<Setter Property="Height" Value="118.718" />
<!--<Setter Property="Canvas.SetLeft"-->
</DataTrigger>
<DataTrigger Value="1">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource ToleranceRangeTypeChecker}">
<Binding ElementName="UserControl" Path="ToleranceZoneLowerBound" />
<Binding ElementName="UserControl" Path="ToleranceZoneUpperBound" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Data" Value="F1M205.917,103.0088C189.333,93.8108 170.128,88.9998 150,88.9998 150,113.365662567029 150,208.7178 150,208.7178L183.9,144.2508z" />
<Setter Property="Width" Value="111.75" />
<Setter Property="Height" Value="118.718" />
<!--<Setter Property="Canvas.SetLeft"-->
</DataTrigger>
</Style.Triggers>
</Style>
Another thought I had was to instead actually have 3 different paths and use setters to change the visibility of each, but I think that having one path and changing it's propertise would be more logical. I would also prefer one path because my goal would be to eventually animate between the paths rather than have them change instantly.
Thanks!
You can get the instance by casting the sender parameter in the property change callbacks.

Categories