I have a property of datattype enum : like
public BreakLevel Level
{
get { return level; }
set { level = value; }
}
And enum defined :
public enum BreakLevel
{
Warning, Fatal
}
I want bind the neum property to the visibility of my border , somewhat like this:
Visibility="{Binding BreakLevel.Fatal}"
so is it possible?
<Border CornerRadius="4" BorderThickness="1" BorderBrush="#DAE0E5"
Visibility="{Binding DataContext.IsError, Converter={StaticResource BoolToVisibilityConverter}, RelativeSource={RelativeSource TemplatedParent}}" >
Scott has a good answer to the actual question, however its always a good idea to ask yourself "How might I need code like this in the future? How can I avoid creating yet another class and instead re-use what I have already got?".
Here is a more general variation of Scott's solution:-
public class EnumToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (Enum.GetName(value.GetType(), value).Equals(parameter))
return Visibility.Visible;
else
return Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
Xaml:-
<TopLevelWindowOrControl.Resources>
<local:EnumToVisibilityConverter x:Key="EnumToVisibilityConverter" />
</TopLevelWindowOrControl.Resources>
<Border Visibility="{Binding Path=BreakLvlProperty, Converter={StaticResource EnumToVisibilityConverter}, ConverterParameter=Fatal" />
In this approach we can converter any enum to a Visibility value by using the ConverterParameter to specify the enum value (in string form) that constitute the "Visible" state.
Its tempting to take this further to allow more than one enum value to be equated to "Visible". However currently the code isn't much more complicated than Scott's more specific implementation. Hence this enhancement should be left until needed.
I think you can just create a BreakLevelToVisibilityConverter and bind just like the example you provided.
I'm assuming that the DataContext of your border is set to an instance of a class that has a property of type 'BreakLevel' (we'll call this property 'BreakLvlProperty').
The code below will then show the border if the value of BreakLvlProperty is BreakLevel.Fatal
Converter:
public class BreakLevelToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((BreakLevel)value == BreakLevel.Fatal)
return Visibility.Visible;
else
return Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
XAML:
<TopLevelWindowOrControl.Resources>
<local:BreakLevelToVisibilityConverter x:Key="BreakLevelToVisibilityConverter" />
</TopLevelWindowOrControl.Resources>
<Border Visibility="{Binding Path=BreakLvlProperty, Converter={StaticResource BreakLevelToVisibilityConverter}" />
public class EnumToVisibilityConvertor : IValueConverter
{
private bool chk;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((value != null) && (value is BreakLevel) && (targetType == typeof(Visibility)))
{
chk = ((((BreakLevel) value) == (BreakLevel) Enum.Parse(typeof (BreakLevel), parameter.ToString(), true)));
return (chk==true) ? Visibility.Visible : Visibility.Collapsed;
}
throw new InvalidOperationException("Invalid converter usage.");
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
<Border CornerRadius="4" BorderThickness="1" BorderBrush="#DAE0E5"
Visibility="{Binding Path=Level, Converter={StaticResource enumToVisibilityConvertor},ConverterParameter=Fatal}" >
I know it's a bit old question but all of you focused on converters and there's much better (in my opinion) way of doing it without involving code-behind:
<ContentControl>
<ContentControl.Template>
<ControlTemplate>
<Grid>
<!-- Here is the border which will be shown if Object.Level has value Fatal -->
<Border x:Name="PART_Border"
Visibility="Collapsed"
BorderThickness="3" BorderBrush="Red"
CornerRadius="4">
</Border>
<TextBlock>Interiors of the border</TextBlock>
</Grid>
<ControlTemplate.Triggers>
<!-- This is the code which turns on border's visibility -->
<DataTrigger Binding="{Binding Level}" Value="{x:Static local:BreakLevel.Fatal}">
<Setter TargetName="PART_Border" Property="Visibility" Value="Visible" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
I assumed that in DataContext resists an object which has a property Level which is of your BreakLevel type.
Related
I have a DataTemplate:
<DataTemplate
DataType="{x:Type local:ConnectionViewModel}"
>
<!-- The connection is represented by a curved arrow. -->
<ca:CurvedArrow
StrokeThickness="2"
Points="{Binding Points}"
Fill="{StaticResource connectionBrush}"
Stroke="{StaticResource connectionBrush}"
/>
</DataTemplate>
This represent all the connector i have in my view.
What I want to do is to set a different fill and stroke for specific specific connectors from the viewmodel.
How can I achive that?
You should be avoiding any UI objects in viewmodel.
For the mentioned use case, you can make use of Converters and continue to only have business object level information in your viewmodel.
For instance, you Connection class can hold a property of enum : ConnectorType {Arrow,Circle,Rectangle} and then you can write a Converter which converts enum type to desired color brush. Sample code below:
//Inside Resources. local=namespace where you have this converter
<local:ConnectorType2BrushConverter x:Key="ConnectorType2BrushConverter" />
....
<ca:CurvedArrow
StrokeThickness="2"
Points="{Binding Points}"
Fill="{Binding Path=ConnectorType, Converter={StaticResource ResourceKey=ConnectorType2BrushConverter}"
/>
....
public class ConnectorType2BrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var connectorType = (ConnectorType)value;
if (connectorType == ConnectorType.Arrow)
{
return new SolidColorBrush(Color.FromRgb(1, 1, 1));
}
else .....
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Want to hide and show property grid for SelectedItem in listview
<UserControl xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
<ListView>
<!--here is list view-->
</ListView>
<xctk:PropertyGrid SelectedObject="{Binding Active}" Visibility="{Binding Active, Converter=NullToVisibilityConverter}" >
</xctk:PropertyGrid>
</UserControl>
So I need converter and use it in visibility property converter. Any help?
public class NullVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Hidden : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then reference the NullVisibilityConverter in your XAML Resources.
<StackPanel.Resources>
<simpleXamlContent:NullVisibilityConverter x:Key="NullToVisibilityConverter"/>
</StackPanel.Resources>
To use the converter we can create one in the resources, and refer to it as a static resource in the binding statement.
<UserControl xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
<UserControl.Resources>
<yournamespace:NullVisibilityConverter x:Key="NullToVisibilityConverter"/>
</UserControl.Resources>
<ListView>
<!--here is list view-->
</ListView>
<xctk:PropertyGrid SelectedObject="{Binding Active}" Visibility="{Binding Active, Converter={StaticResource NullToVisibilityConverter}}" >
</xctk:PropertyGrid>
</UserControl>
and Converter class itself
public class NullVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Hidden : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
There is little more useful version allows to set default invisibility value:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string defaultInvisibility = parameter as string;
Visibility invisibility = (defaultInvisibility != null) ?
(Visibility)Enum.Parse(typeof(Visibility), defaultInvisibility)
: Visibility.Collapsed;
return value == null ? invisibility : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
Where ever in resources add:
<converters:NullReferenceToVisibilityConverter x:Key="NullToVis" />
And use it like there:
<StackPanel Visibility="{Binding MyObject, Converter={StaticResource NullToVis}}">
<StackPanel Visibility="{Binding MyObject, Converter={StaticResource NullToVis}, ConverterParameter=Hidden}">
<DataGrid....
<DataGrid.Resources>
<DataTemplate DataType="{x:Type DateTime}">
<TextBlock Text="{Binding StringFormat={}{0:d}}" />
</DataTemplate>
</DataGrid.Resources>
...
<DataGridTemplateColumn Header="Время оплаты">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center" Text="{Binding date_payment}" Width="Auto" Height="Auto" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
but this column have type DateTime...
i need convert this column on this type(string), because i need rename value row on this column, i use event LoadingRow so
DataRowView item = e.Row.Item as DataRowView;
DataRow row = item.Row;
var time = row[4];
if (Convert.ToString(time) == "01.01.0001 0:00:00")
{
row[4] = "No payment";
}
but its wrong, row no converting to string, please help
First of all, you have both a cell template and a data template. Pick one. Second, since you have a data template anyway there's no reason to create a converter, much less a code-behind event handler. You can keep all the relevant code and text strings (what if you need to localize?) nicely in one place with a trigger:
<DataTemplate TargetType="{x:Type DateTime}">
<TextBlock x:Name="text" Text="{Binding StringFormat={}{0:d}}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding}" Value="{x:Static DateTime.MinValue}">
<Setter TargetName="text" Property="Text" Value="No payment"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
In case if it's Nullable value you could use
Binding="{Binding date_payment, TargetNullValue={}Дата отсутствует}"
In case if not, use IValueConverter where you will check for MinDate.
Here is an Example how to use converters, and converter for you
public class DateConverter:IValueConverter
{
private const string NoDate = "Дата отсутствует";
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is DateTime)
{
var date = (DateTime) value;
if(date==DateTime.MinValue)
return NoDate;
return date.ToString();
}
return NoDate;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
You shoud use Converter for this:
public class MyConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
if (value == DateTime.MinValue) {
return "No payment";
}
return value.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
throw new NotImplementedException();
}
}
Than just add the converter to your binding.
I need to make some complex binding in XAML. I have a DependencyProperty typeof(double); let's name it SomeProperty. Somewhere in XAML code of my control, I need to use the whole SomeProperty value, somewhere only a half, somewhere SomeProperty/3, and so on.
How can I do something like:
<SomeControl Value="{Binding ElementName=MyControl, Path=SomeProperty} / 3"/>
:)
Looking forward.
Use a division ValueConverter:
public class DivisionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int divideBy = int.Parse(parameter as string);
double input = (double)value;
return input / divideBy;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
<!-- Created as resource -->
<local:DivisionConverter x:Key="DivisionConverter"/>
<!-- Usage Example -->
<TextBlock Text="{Binding SomeProperty, Converter={StaticResource DivisionConverter}, ConverterParameter=1}"/>
<TextBlock Text="{Binding SomeProperty, Converter={StaticResource DivisionConverter}, ConverterParameter=2}"/>
<TextBlock Text="{Binding SomeProperty, Converter={StaticResource DivisionConverter}, ConverterParameter=3}"/>
Just wondering if it is possible to show a WPF on a disabled item ONLY (and not when the item is enabled).
I would like to give the user a tooltip explaining why an item is currently disabled.
I have an IValueConverter to invert the boolean IsEnabled property binding. But it doesn't seem to work in this situation. The ToolTip is show both when the item is enabled and disabled.
So is is possible to bind a ToolTip.IsEnabled property exclusively to an item's own !IsEnabled?
Pretty straightforward question I guess, but code example here anyway:
public class BoolToOppositeBoolConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (targetType != typeof(bool))
throw new InvalidOperationException("The target must be a boolean");
return !(bool)value;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (targetType != typeof(bool))
throw new InvalidOperationException("The target must be a boolean");
return !(bool)value;
}
#endregion
}
And the binding:
<TabItem Header="Tab 2" Name="tabItem2" ToolTip="Not enabled in this situation." ToolTipService.ShowOnDisabled="True" ToolTipService.IsEnabled="{Binding Path=IsEnabled, ElementName=tabItem2, Converter={StaticResource oppositeConverter}}">
<Label Content="Item content goes here" />
</TabItem>
Thanks folks.
JustABill's suggestion worked. I also needed to define the string as a resource to avoid problems with quotation marks. And you still need to set ToolTipService.ShowOnDisabled="True".
So, here is the working code which shows how to display a tooltip in WPF only when an item is disabled.
In the top container, include the system namespace (see sys below). I also have a Resources namespace, which I called "Res".
<Window x:Class="MyProjectName.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:Res="clr-namespace:MyProjectName.Resources"
>
Then you need
<Window.Resources>
<Res:FalseToStringConverter x:Key="falseToStringConv" />
<sys:String x:Key="stringToShowInTooltip">This item is disabled because...</sys:String>
</Window.Resources>
In my case, it was a tab item that I was interested in. It could be any UI element though...
<TabItem Name="tabItem2" ToolTipService.ShowOnDisabled="True" ToolTip="{Binding Path=IsEnabled, ElementName=tabItem2, Converter={StaticResource falseToStringConv}, ConverterParameter={StaticResource stringToShowInTooltip}}">
<Label Content="A label in the tab" />
</TabItem>
And the converter in code behind (or wherever you want to put it). Note, mine went into the a namespace called Resources, which was declared earlier.
public class FalseToStringConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is bool && parameter is string)
{
if ((bool)value == false)
return parameter.ToString();
else return null;
}
else
throw new InvalidOperationException("The value must be a boolean and parameter must be a string");
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
A little out of date, but I got this working by setting RelativeSource mode to Self instead of setting the ElementName within the Binding.
<TabItem Header="Tab 2" Name="tabItem2" ToolTip="Not enabled in this situation." ToolTipService.ShowOnDisabled="True" ToolTipService.IsEnabled="{Binding Path=IsEnabled, RelativeSource={RelativeSource Mode=Self}, Converter={StaticResource oppositeConverter}}">
<Label Content="Item content goes here" />
</TabItem>