Telerik WPF GridView header text disappears when content is bound to tooltip - c#

I am following Telerik guide for displaying a tooltip on WPF GridView column headers. The task is to create a tooltip which would have same text as column header.
In generic.xml there is this style:
<Style TargetType="telerik:GridViewHeaderCell">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content}" />
</Style>
This does work and shows a tooltip when mouse is hovered over column header, however the actual header is being cleared.
I wonder why this is happening and how to fix it? GridViewHeaderCell inherits from ContentControl.

I ended up adding a converter because "Content" value appeared to be a TextBlock:
public class TooltipObject : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
return ((TextBlock)value).Text;
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
and the style looks like:
<utils:TooltipObject x:Key="tooltip" />
...
<Style TargetType="telerik:GridViewHeaderCell">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content, Mode=TwoWay, Converter={StaticResource tooltip}}" />
</Style>

Related

Converter to Bool

I have a normal Checkbox, where I want to set the IsChecked property to a Binding resource.
The resource is a self written class myClass, which can be null or referenced (means not null).
The Checkbox should be NOT checked, if the assigned object myObject (out of myClass) is null
and checked, if it is not null.
What do I have to write in the IsChecked="..." property in my xaml file?
You can create a style with a DataTrigger that sets the IsChecked property.
<CheckBox>
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource {x:Type CheckBox}}">
<Setter Property="IsChecked" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding MyObject}" Value="{x:Null}">
<Setter Property="IsChecked" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
An alternative is to create a reusable value converter.
public class NotNullToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value != null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException();
}
}
Create an instance of the converter in any resource dictionary, e.g. application resources.
<local:NotNullToBooleanConverter x:Key="NotNullToBooleanConverter"/>
This converter can be used directly in the binding.
<CheckBox IsChecked="{Binding MyObject, Converter={StaticResource NotNullToBooleanConverter}}"/>

WPF ListBox showing empty row created by DataGrid

I have both DataGrid and Listbox binded to the same ObservableCollection:
public ObservableCollection<Contact> contacts = new ObservableCollection<Contact>();
CntGrid.ItemsSource = contacts;
CntListBox.ItemsSource = contacts;
<DataGrid x:Name="CntGrid"
IsReadOnly="False"
CanUserAddRows="True"
CanUserDeleteRows="True"/>
<ListBox x:Name="CntListBox"/>
The problem is DataGrid allowing adding items (I want to keep this functionality) causes ListBox to display an empty row aswell. I don't want my ListBox to display this empty row at the end.
Can I somehow modify my ListBox to fix this?
This will hide the {NewItemPlaceholder} item in your ListBox:
<ListBox x:Name="CntListBox">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<DataTrigger Binding="{Binding}" Value="{x:Static CollectionView.NewItemPlaceholder}">
<Setter Property="UIElement.Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Empty row in DataGrid is a NewItemPlaceholder. It has different type from Contact. So I suggest to use a converter to hide it in ListBox:
public class ObjectTypeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var t = parameter as Type;
if (value == null || t == null)
return false;
return t.IsAssignableFrom(value.GetType());
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
use that converter in ListBoxItem Style to check the type of item and hide them if type doesn't match:
<Window.Resources>
<local:ObjectTypeConverter x:Key="tc"/>
</Window.Resources>
<ListBox x:Name="CntListBox">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Converter={StaticResource tc}, ConverterParameter={x:Type local:Contact}}"
Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>

Replacing delete button with restore depending on boolean value in WPF

I have boolean column named "deleted" in mysql.
1)if the row is not deleted it shows the delete button.
2)if the row is deleted it should display retore button in that datagrid cell instead of deleted with the query of restore behind it.
right now i can only disable the button if the row is deleted.
My code is as follows.
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Delete" Name="btnDelete"
Click="btnDelete_Click">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding deleted}" Value="False">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
The main idea is using converter that will convert bool value to visibility.
However, for restore button, you will need to invert the visibility behavior, therefore custom converter comes in mind
public class BoolToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is bool boolValue))
throw new InvalidOperationException();
if (parameter == null || (parameter is bool invertVisibility && !invertVisibility))
return boolValue ? Visibility.Visible : Visibility.Collapsed;
else
return boolValue ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then your buttons will use the same converter registered as:
<Window.Resources>
<local:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"></local:BoolToVisibilityConverter>
</Window.Resources>
But one of them will pass additional parameter so that converter will invert its logic:
<Button Margin="5" Content="Delete"
Visibility="{Binding deleted, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter=true}"
Command="{Binding DeleteCommand}"></Button>
<Button Margin="5" Content="Restore"
Visibility="{Binding deleted, Converter={StaticResource BoolToVisibilityConverter}}"
Command="{Binding RestoreCommand}"></Button>
You can use the built-in BoolToVisibilityConverter and set the Visibility Property, you might not need a trigger for this
...
<Window.Resources>
<BooleanToVisibilityConverter x:Key="VisibleIfTrueConverter" />
</Window.Resources>
...
<Button Visibility={Binding deleted, Converter={StaticResource VisibleIfTrueConverter}}/>

DataTriggerBehavior is not working for null values

I am trying to set visibility of my stackpanel to collapsed if value is null, but DataTriggerBehavior is not changing it's visibility value, If I change value to something else than it work's, below is the xaml for that:
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding Name}"
Value="{x:Null}">
<Core:ChangePropertyAction TargetObject="{Binding ElementName=spName}"
PropertyName="Visibility"
Value="Collapsed" />
</Core:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>
One option is to use a simple converter which presumes Name is a String and returns an empty String if value is null else returns the value as a String
public class NullToEmptyStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value == null)
return "";
else
return value.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
And your xaml will reference NullToEmptyStringConverter NB local is the namespace where I've created the converter class it maybe different in your app
<Page.Resources>
<local:NullToEmptyStringConverter x:Key="NullToEmptyStringConverter"/>
</Page.Resources>
and your DataTrigger
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding Name, Converter={StaticResource NullToEmptyStringConverter}}"
Value="">
<Core:ChangePropertyAction TargetObject="{Binding ElementName=spName}"
PropertyName="Visibility"
Value="Collapsed" />
</Core:DataTriggerBehavior>

How to set a nullable property value by Style setter?

I am developing a Windows Store (8.1) application.
I have this control which has a nullable int property (type "int?"), when I try to set it to an int via Style, I get an error.
<Setter Property="Minimum" Value="0" />
Error Cannot assign to nullable type on property Minimum
Any ideas?
Following sample depicts solution, adjust it to your demands.
C#:
class IsNullToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value == null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML:
<Window.Resources>
<local:IsNullToBoolConverter x:Key="IsNullToBoolConverter"/>
</Window.Resources>
<TextBlock Text="Text">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Age, Converter={StaticResource IsNullToBoolConverter}}" Value="False">
<Setter Property="FontSize" Value="55"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
you can achieve this by using TargetNullValue property. Use below code,
TargetNullValue={x:Static sys:String.Empty}
Note :
sys is the imported xml namespace for System in mscorlib:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Hope this will help..

Categories

Resources