In my XAML I have an expander like this
<Expander ExpandDirection="Down" Width="Auto" Padding="4">
<Expander.Style>
<Style TargetType="Expander">
<Setter Property="IsExpanded" Value="{Binding XPath=#Expand}" />
<Setter Property="Header" Value="{Binding XPath=#Name}" />
<Setter Property="FontWeight" Value="Bold" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsExpanded,RelativeSource={RelativeSource Self}}" Value="True">
</DataTrigger>
</Style.Triggers>
</Style>
</Expander.Style>
<ListBox Name="itemsList"
ItemsSource="{Binding XPath=UpgradeAction}"
ItemTemplate="{StaticResource dtListItemTemplate}"
SelectionChanged="listItems_SelectionChanged"
Style="{StaticResource styleListBoxUpgradeAction}"
ItemContainerStyle="{StaticResource styleListBoxItemUpgradeAction}">
</ListBox>
</Expander>
Instead of the value of Header to come from #Name I want to have a C# function to take in the #Name from the XAML, do some things, then output a new string which will be used as the Value. So it would look something like this
<Setter Property="Header" Value="C_Sharp_Function({Binding XPath=#Name})" />
I have the function that I need to use but how do I execute this in the XAML?Sorry if this sounds like a stupid question, I'm new to C# and XAML. Any help is much appreciated!
EDIT
Here is some of the things I tried in the Setter to substitute a multi-value converter. I assume it should look something like the answer in this.
<Setter Property="Header" Value="{{Binding XPath=#Name, Converter={StaticResource NameConverter}}, {Binding XPath=#Value, Converter={StaticResource NameConverter}}}" />
<Setter Property="Header" Value="{Binding XPath={#Name, #Value}, Converter={StaticResource NameConverter}}" />
What you're describing is a value converter. It looks a little different, but logically it's the same thing.
public class NameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var name = (XmlAttribute)value;
// Do anything you like in here. This is just an example.
return "something based on " + name.Value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML:
<Window.Resources>
<local:NameConverter x:Key="NameConverter" />
<!-- ... -->
...
<Expander ExpandDirection="Down" Width="Auto" Padding="4">
<Expander.Style>
<Style TargetType="Expander">
<Setter Property="IsExpanded" Value="{Binding XPath=#Expand}" />
<Setter
Property="Header"
Value="{Binding XPath=#Name, Converter={StaticResource NameConverter}}"
/>
If you want to pass in more than one parameter, you can use a multi-binding with a multi-value converter.
I'm not sure why you'd doing all your bindings in the Expander's Style. The following should work equally well. I also included a simpler way to do the IsExpanded trigger.
public class NameValueConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var attrName = (XmlAttribute)values[0];
var attrValue = (XmlAttribute)values[1];
// Do stuff here.
return attrName.Value + " -> " + attrValue.Value;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
<Window.Resources>
<local:NameValueConverter x:Key="NameValueConverter" />
</Window.Resources>
...
<Expander
ExpandDirection="Down"
Width="Auto"
Padding="4"
IsExpanded="{Binding XPath=#Expand}"
>
<Expander.Style>
<Style TargetType="Expander">
<Setter Property="FontWeight" Value="Bold" />
<Style.Triggers>
<!--
You can do a regular Trigger instead of a DataTrigger and not
have to bother with RelativeSource=Self
-->
<Trigger
Property="IsExpanded"
Value="True">
<!-- stuff -->
</Trigger>
</Style.Triggers>
</Style>
</Expander.Style>
<Expander.Header>
<MultiBinding Converter="{StaticResource NameValueConverter}">
<Binding XPath="#Name" />
<Binding XPath="#Value" />
</MultiBinding>
</Expander.Header>
</Expander>
Here's where Window.Resources goes:
<Window
...x:Class="..." and other attributes...
>
<Window.Resources>
<local:NameConverter x:Key="NameConverter" />
<!-- other resources -->
</Window.Resources>
<Grid>
<!-- The controls that go in the window -->
</Grid>
</Window
Related
I'm new to WPF, I have a property that defines an int which is the index of the element to change the background color within the ListView but is changing the background color of all the ListViewItem, here my code:
<ListView AlternationCount="2147483647" x:Name="listView1" HorizontalAlignment="Left" Height="295" Margin="10,10,0,0" VerticalAlignment="Top" Width="380" Padding="0" HorizontalContentAlignment="Center" BorderThickness="1" IsSynchronizedWithCurrentItem="False" SelectionMode="Single" ScrollViewer.CanContentScroll="True">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ContextMenu" Value="{StaticResource ListViewItemContexMenuKey}"/>
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource IndexConverter}">
<Binding Path="AlternationIndex" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ItemsControl}"/>
<Binding Path="TargetIndex" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=Window}"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Background" Value="#FFFF7171"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Here the IndexConverter
public class IndexConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
int index = (int)values[0];
int targetIndex = (int)values[1];
Console.WriteLine($"Index: {index}, TargetIndex: {targetIndex}");
return index == targetIndex;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
In the IndexConverter.Convert the local variable index is the AlternationIndex and always is returning 0.
I don't get why this behaviour, when using trigger it works corretly, but you can't bind using Trigger.
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#FFFF7171"/>
</Trigger>
As pointed out by #elgonzo, ItemsControl.AlternationIndex is an attached property that you should bind to like this:
<Binding Path="(ItemsControl.AlternationIndex)"
RelativeSource="{RelativeSource Self}"/>
Note the parentheses around the path.
I need to show 0 and 1 Boolean values as YES and NO inside the data grid cell.
<DataGridTextColumn Header="Active" Binding="{Binding stuen.IsDelete}" CanUserResize="False" Width="* " HeaderStringFormat="" >
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
Simple enough - You can extend status model with additional property (say YesNo) like :
public string YesNo
{
get {return !IsDelete ? "No" : "Yes"}
}
and now bind your control with status.YesNo rather than status.IsDelete.
Alternatively - You can use BooleanToYesNoConverter in your binding element. Basically converter would return Yes for status.IsDelete = true and No for status.IsDelete=false.
Like :
public class BooleanToYesNoConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if((bool)value) return "Yes";
return "No"
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
/* not sure if you need convert back */
}
}
Add this converter as a static resource in your Xaml :
<Window.Resources>
<local:BooleanToYesNoConverter x:Key="BooleanToYesNoConverter" />
</Window.Resources>
Then update your binding attribute to :
Binding="{Binding stuen.IsDelete Converter={StaticResource BooleanToYesNoConverter}}"
Other Alternative solution would be to use trigger like below :
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Text" Value="" />
<Style.Triggers>
<DataTrigger Binding="{Binding status.IsDelete}" Value="Yes">
<Setter Property="Text" Value="No" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
You could replace the DataGridTextColumn with a DataGridTemplateColumn:
<DataGridTemplateColumn Header="Active" CanUserResize="False" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="NO" />
<Style.Triggers>
<DataTrigger Binding="{Binding stuen.IsDelete}" Value="True">
<Setter Property="Text" Value="YES" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I want to create the TextBox that has the Text-hint to describe TextBox value.
for this purpose I use VisualBrush that has TextBlock shows the TextBox hint when the TextBox is empty , then i coded the converter to convert HorizontalContentAlignment of TextBox(control that applied the style) To AlignmentX means that when objective TextBox e.g is left then the visualBrush shows left Alignment TextBlock but this pupose not came true.
how I can fix this like bellow:
My XAML Code:
<Window.Resources>
<local:HorizontalAlignToAlignX x:Key="HAligToXAlig"/>
<Style TargetType="{x:Type TextBox}" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush"
Stretch="None"
AlignmentX="{Binding HorizontalContentAlignment, Converter={StaticResource HAligToXAlig}}">
<VisualBrush.Visual>
<TextBlock Text="search" Foreground="LightGray"/>
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<TextBox x:Name="textBox"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="342"
HorizontalContentAlignment="Right" />
</Grid>
My Converter Code:
class HorizontalAlignToAlignX : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
AlignmentX Align = AlignmentX.Right;
switch ((HorizontalAlignment)value)
{
case HorizontalAlignment.Left:
Align = AlignmentX.Left;
break;
case HorizontalAlignment.Center:
Align = AlignmentX.Center;
break;
case HorizontalAlignment.Right:
Align = AlignmentX.Right;
break;
case HorizontalAlignment.Stretch:
Align = AlignmentX.Center;
break;
default:
break;
}
return Align;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
I fund my answer by RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TextBox}} like bellow:
<Window.Resources>
<local:HorizontalAlignToAlignX x:Key="HAligToXAlig" />
<Style TargetType="{x:Type TextBox}"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush"
Stretch="None"
AlignmentX="{Binding ConverterParameter=HorizontalContentAlignment, Converter={StaticResource HAligToXAlig}, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TextBox}}, Path=HorizontalContentAlignment}">
<VisualBrush.Visual>
<TextBlock Text="search"
Foreground="LightGray"
TextAlignment="Right" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text"
Value="{x:Static sys:String.Empty}">
<Setter Property="Background"
Value="{StaticResource CueBannerBrush}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<TextBox x:Name="textBox"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="342"
HorizontalContentAlignment="Right" />
</Grid>
i've a WPF DataGrid with different count of columns. I want to color the single cells dependent by the value.
For example: If the cell-value is 0, then red.
These are my experiments:
<DataGrid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" x:Name="DataGrid" SelectionUnit="Cell">
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<!--experiment 1 -->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Value, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}" Value="0">
<Setter Property="Background" Value="LimeGreen"/>
</DataTrigger>
<!--experiment 2 -->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Content, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}" Value="0">
<Setter Property="Background" Value="LimeGreen"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
</DataGrid>
Just use a value converter (with the cell value as a parameter), that returns the color you want.
<DataGrid>
<DataGridCell Background="{Binding CellValueField, Converter={StaticResource YourDefinedValueToColorConverter}}" />
</DataGrid>
EDIT: Finally got it to work.
Converter and style definitions:
<Window.Resources>
<c:ValueToColorConverter x:Key="ValueToColorConverter"/>
<Style x:Key="CellStyle" TargetType="DataGridCell">
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource ValueToColorConverter}}" />
</Style>
</Window.Resources>
The DataGrid:
<DataGrid HorizontalAlignment="Left"
Margin="10,10,0,0"
VerticalAlignment="Top"
Loaded="DataGrid_Loaded">
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="{Binding Converter={StaticResource ValueToColorConverter}}" />
</Style>
</DataGrid.CellStyle>
</DataGrid>
And the converter:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var cell = value as Order;
if (cell != null && cell.Size > 80)
return new SolidColorBrush(Colors.Red);
else return new SolidColorBrush(Colors.Yellow);
}
I used the DataGrid_Loaded method to fill the DataGrid with some random data encapsulated in a sample class:
class Order
{
public int Size { get; set; }
}
And the result:
Use a value converter, like this:
<DataGridCell Background="{Binding CellValueField, Converter={StaticResource IntegerToColorValueConverter}}" />
And:
public class IntegerToColorValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
switch ((int)value)
{
case 1: return Color.Red; break;
case 2: return Color.Yellow; break;
Default: return Color.White; break;
}
}
}
In my application, I have used "DataGrid" to bind set of values dynamically. Also based upon the values binded, I need to change the forecolor of the values binded.
Here is my XAML and C# code
XAML:
<my:DataGridTemplateColumn Header="Priority">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment="Left" Name="txtPriority" Text="{Binding MessagePriority}" FontWeight="Bold">
<TextBlock.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{Binding ForegroundBrush}" />
</Style>
</TextBlock.Resources>
</TextBlock>
</my:DataGrid.Columns>
</my:DataGrid>
C#:
private SolidColorBrush _foregroundBrush;
public SolidColorBrush ForegroundBrush
{
get
{
return _foregroundBrush;
}
set
{
if (_foregroundBrush != value)
{
_foregroundBrush = value;
RaisePropertyChanged(() => _foregroundBrush);
}
}
}
var color = (Color)ColorConverter.ConvertFromString("#FF00FF");
var brush = new SolidColorBrush(color);
ForegroundBrush = brush;
There are a couple of ways that you can do this. It very much depends on your requirements, so it would have been better if you had explained them better and in more detail. However as you didn't, I can't use your exact details in this example and you will have to adapt it to your project. The first way is to simply use a DataTrigger... this method is good for up to around 8 different value/colour pairs:
<DataGrid ItemsSource="{Binding RadioButtonData}">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Label}">
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding SomeValue}" Value="Something">
<Setter Property="TextElement.Foreground" Value="LightGreen" />
</DataTrigger>
<DataTrigger Binding="{Binding SomeValue}" Value="Another thing">
<Setter Property="TextElement.Foreground" Value="LightBlue" />
</DataTrigger>
<DataTrigger Binding="{Binding SomeValue}" Value="A different thing">
<Setter Property="TextElement.Foreground" Value="LightPink" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
The other method that you can use is to use a Converter class with your Binding. You can find a detailed example of doing this in many online posts... here are a few:
How to set Foreground of DataGrid Column with ValueConverter
Datagrid AutoGenerateColumns="True" forecolor IValueConverter
Hai Everyone,
First of all i thanks to all for see my question and at that time send your answers. Now, i got the answer, i have to use the converter class for convert color to Solidcolorbursh like as below:
ValueConverter.cs
public class ValueConverter : IValueConverter
{
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null || !(value is decimal))
return new SolidColorBrush(ForegroundBrush);
var dValue = System.Convert.ToDecimal(value);
if (dValue < 0)
return new SolidColorBrush(ForegroundBrush);
else
return new SolidColorBrush(ForegroundBrush);
}
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
XMAL:
First we can decalre that class namespace like:
xmlns:convert="clr-namespace:Helper"
<Grid.Resources>
<convert:ValueConverter x:Key="ValueConverter"></convert:ValueConverter>
</Grid.Resources>
<my:DataGridTemplateColumn Header="Priority">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment="Left" Name="txtPriority" Text="{Binding Priority}" FontWeight="DemiBold" Foreground="{Binding Priority, Converter={StaticResource ValueConverter}}">
</TextBlock>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>