ValueConversion only when not selected - c#

I have a TextBox which displays a file path to the user. The user can either use a OpenFileDialog to pick the file, which updates the text, or directly write/paste the path into the text box.
However, the text box is constrained in size and to avoid the path being cut off I'm using an custom IValueConverter to cut off part of the path to make sure both the drive letter, and the file name is visible.
For example,
C:\Users\USERNAME\Documents\CompanyName\ExportType\ExportName\Exportfile1.bin
becomes
C:\...\ExportType\ExportName\Exportfile1.bin
The problem occurs then when the user selects the field. As expected, the ConvertBack method of the IValueConverter is triggered, with the value now being the shortened path.
Is it then possible, without creating some custom intricate custom control, to show one formatted value when it's not selected, and the raw value when selected?
(I have access to the Telerik UI components, if it's already such a component there)

I came up with solution without code behind
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Text">
<Setter.Value>
<Binding Path="nazwa" Converter="{StaticResource converter}" ConverterParameter="false"/>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Foreground" Value="Gold"/>
<Setter Property="Text">
<Setter.Value>
<Binding Path="nazwa" Converter="{StaticResource converter}" ConverterParameter="true"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
Converter
public class conv : IValueConverter
{
private string track = null;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
track = value.ToString();
return parameter.ToString().Equals("true") ? track: track.Substring(0,2);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Result when textbox is not selected
and when I select
just changing color yet, bytheway. The trick was to change parameters sending to converter. Let me know whether it works.

Related

Cannot Make Binding to ZIndex from Another Element in WPF

I want to make binding to the ZIndex of another element in WPF in the same .xaml file but it does not work.
The element to be bound.
<Border
x:Name="BubbleTop"
CornerRadius="5"
Background="#EBF5EB"
Padding="8,6"
BorderBrush="LightGray"
BorderThickness="1"
Grid.ZIndex="3">
<ContentPresenter />
</Border>
The element who initial a binding.
<TextBlock
x:Name="statusText"
Margin="..."
Foreground="{Binding ElementName=BubbleTop, Path=Grid.ZIndex, Converter={StaticResource ToggleColorConverter}}"
FontWeight="Bold"
Text="..."/>
In the converter, it is set to change the Foreground color according to the ZIndex of the Border element.
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int z = (int)value;
if (z == 3)
return "Red";
else
return "Blue";
}
But it does not work. Any hint?
The converter you have would work fine, except that the Path for your binding is wrong. When binding to an attached property, you have to put the path in parens for the path to be parsed correctly.
That said, I don't think a converter really makes much sense here. You can use styling to address a simple toggle like this. This allows you to keep more of the view logic in XAML.
For example:
<TextBlock
x:Name="statusText"
Margin="..."
FontWeight="Bold"
Text="...">
<TextBlock.Style>
<p:Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Blue"/>
<p:Style.Triggers>
<DataTrigger Binding="{Binding ElementName=BubbleTop, Path=(Grid.ZIndex)}" Value="3">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</p:Style.Triggers>
</p:Style>
</TextBlock.Style>
</TextBlock>
(Note: you can omit the p: XML namespace for the <Style/> element. I include that only because the Stack Overflow code formatter gets confused when there's a plain <Style/> element in XML and won't format the XML correctly.)
Try this in your value converter:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int z = (int)value;
if (z == 3)
return Brushes.Red;
else
return Brushes.Blue;
}

WPF RibbonTab - cannot bind to RibbonTab Headerstyle

I try to customize the RibbonTabHeader with different colors.
However I'm unable to bind dynamic values to the object RibbonTabHeader. One can customize its style by assigning a style to HeaderStyle. But the get of the binded method BackgroundColor is never called.
Xaml:
<Style TargetType="{x:Type ribbon:RibbonTab}">
<Setter Property="Header" Value="{Binding Header}" />
<Setter Property="ItemsSource" Value="{Binding GroupDataCollection}" />
<Setter Property="Visibility" Value="{Binding IsVisible}" />
<Setter Property="IsEnabled" Value="{Binding IsEnabled}"/>
<Setter Property="HeaderStyle">
<Setter.Value>
<Style TargetType="{x:Type ribbon:RibbonTabHeader}">
<Setter Property="Background" Value="{Binding BackgroundColor}"/>
</Style>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="#333333" />
</Style>
Code behind:
public string BackgroundColor
{
get { return "Black"; }
}
When I create the style dynamically in the code behind and assign it to HeaderStyle it is actually working. But this doesn't seem to me as an option as my style will become much more complicated (I have to remove gradients, paint a horizontal rectangle, adjust borders, ..). So it will get complicated to create all dynamically in the code behind.
The other bindings that are directly called in RibbonTab i.e. IsEnabled are actually working.
What is working is this code:
In Xaml:
<Setter Property="HeaderStyle" Value="{Binding Style}"/>
In the code behind:
public Style Style
{
get
{
Style style = new Style(typeof (RibbonTabHeader));
style.Setters.Add(new Setter(RibbonTabHeader.BackgroundProperty, Brushes.Green));
return style;
}
}
Any ideas how I can bind dynamic values to the object RibbonTabHeader ?
I was thinking of defining a style in the xaml and then load it via LoadResource in the codebehind. But I'm not sure if I can clone it later to assign all different colors to different tabs.
After days of research I still didn't find a propper answer to my question.
I nevertheless found a workaround to make it work.
What I finally did is to us a CustomConverter to exploit the tab name that is dynamically bound.
The Converter that is returning a different color based on each tab name looks like this:
public class TabNameToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value.ToString() = "tabName")
return "Red";
return "Black";
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
The Xaml looks like this (Content is the name of the Tab, it is replacing the background color)
<UserControl.Resources>
<ResourceDictionary>
<Converters:TabNameToColorConverter x:Key="TabNameToColorConverter" />
</ResourceDictionary>
</UserControl.Resources>
<Style TargetType="{x:Type ribbon:RibbonTabHeader}">
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content,Converter={StaticResource TabNameToColorConverter}}"/>
</Style>

Displaying "NaN" in a cell depending on the datasource value

I have a Style on my data grid cell defined as follows:
<Style TargetType="{x:Type Editors:XamNumericEditor}" x:Key="MyVisibleStyle" BasedOn="{StaticResource InPointStyle}">
<Setter Property="Mask" Value="-nnnnnnnnnnn.nnnn"/>
<Setter Property="Format" Value="#,##0.000;-#,##0.000" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DataItem.IsPermissioned}" Value="False" >
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
</Style.Triggers>
</Style>
So depending on the value of DataItem.IsPermissioned I set the Visibility of the cell.
How can I change this so that if IsPermissioned=false then I display "NaN" in the cell?
Did you try creating a converter, which implements IValueConverter?
In the binding you would use it like
Binding="{Binding Path=Something, Converter={StaticResource yourConverter}}"
and your converter would be something like
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (validation on the value)
{ return "NaN" } }
You need to alternate the content property instead. So use the part below or add your own content depending on the cell pattern.
<Setter Property="Content" Value="NaN" />

Is it possible to pass a parameter (a Binding) to a WPF Style

I have a WPF style that I am applying to list box items. Currently, each item is bound to a KeyValuePair. I display the Key in a TextBlock inside the ListBoxItem:
<TextBlock Name="Label" Text="{Binding Key}" />
What I want to do is make the Style generic so that if the data is not a KeyValuePair, (maybe just a string), I can bind the data correctly to the TextBlock.
Is there a way to pass a parameter to a Style or DataTemplate or make the data binding generic?
My style:
<Style x:Key="ListBoxItemStyle" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="Border" Padding="2" SnapsToDevicePixels="true" CornerRadius="4" BorderThickness="1">
<TextBlock Name="Label" Text="{Binding Key}" />
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter TargetName="Border" Property="Background" Value="{StaticResource SelectionGradient}" />
</MultiTrigger>
<ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Let me give you a quick example. Let's say your TextBox contains a number, and you want it to be with a red Background if the number is negative, or with a green background if >= 0
Here is the style you'd write:
<TextBlock Text="{Binding Key}" >
<TextBlock.Style>
<Style TargetType="TextBox">
<Setter Property="Background" Value="{Binding Key, Converter={StaticResource MyConverterResource}" />
</Style>
</TextBlock.Style>
</TextBlock>
Here is the converter you'd write:
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double source = (double)value;
return source < 0 ? Brushes.Red : Brushes.Green;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// We don't care about this one here
throw new NotImplementedException();
}
}
And, to access the converter in your xaml, you just have to do the following, assuming your converter is in the namespace MyNamespace:
<Window xmlns:my="clr-namespace:MyNamespace">
<Window.Resources>
<my:MyConverter x:Key="MyConverterResource">
</Window.Resources?
<!-- Your XAML here -->
</Window>
(of course you can put this in any Resources, may it be a UserControl or whatever )
This will allow you to call your converter by writing {StaticResource MyConverterResource}
And here, you'd have a conditional style, the converter deciding which color to set as a background according to one parameter, in my case, the value itself (but it can be whatever you want)

How to dynamically set the Row's text to bold, using MVVM, C# and no Code-Behind?

I'm developing a WPF Page using .NET, MVVM, no code-behind, using PropertyChanged. In this Page, I have a DataGrid with a lot of columns.
Into the DB, one of the Columns, let's call it HIGHLIGHT, will have values S or N. If value = S, the entire line will be Bold, or ExtraBold. Case N = Normal.
I made this work using this code in XAML:
<Style x:Key="TextRowStyle" TargetType="{x:Type TextBlock}" >
<Style.Triggers>
<DataTrigger Binding="{Binding Slab.Highlight}" Value="S">
<Setter Property="FontWeight" Value="ExtraBold"/>
</DataTrigger>
</Style.Triggers>
</Style>
But doing in this way, I'll have to put in EVERY COLUMN, this code to make it work (Notice the ElementStyle):
<DataGridTextColumn Header="Test" Binding="{Binding SlabSeq}" ElementStyle="{StaticResource TextRowStyle}"/>
What do I need:
Each table of my DB has several Columns, over 60, 70, and i'm searching for a way to make this more easy, like the StaticResource TextRowStyle i've made...
Another thing i've made, it was a Converter:
public class HighlightConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (System.Convert.ToChar(value).Equals("S"))
return FontWeights.ExtraBold;
else
return FontWeights.Normal;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return FontWeights.ExtraBold;
}
}
I'd tried to make a converter inside those fields, using:
<Page.Resources>
<vm:HighlightConverter x:Key="HighlightConverter"/>
</Page.Resources>
and into the Grid:
<TextBlock FontWeight={Binding Slab.Highlight, Converter={StaticResource HighlightConverter}}"/>
Does anyone have any idea of how I can make this work?
Best regards,
Gustavo.
why you dont create a "local" style in your DataGrid.Resources. did i get it right that the entire row has to be bold (S) or normal (N)?
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridCell}" >
<Setter Property="FontWeight" Value="Normal"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Slab.Highlight}" Value="S">
<Setter Property="FontWeight" Value="ExtraBold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
with the code above all cells would be normal, but if a datarow has Slab.Highlight=S all cells would be bold. the code is not tested. maybe you have to add TextBlock.Fontweight or something like that.
What about applying the style implicitly by dropping the x:Key? That should make it apply everywhere in the grid when placed in the DataGrid.Resources.
This might work. Sorry, it's untested as I'm nowhere near an IDE.
<DataGrid>
<DataGrid.Resources>
<Style TargetType="DataGridTextColumn">
<Style.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontWeight" Value="{Binding Slab.Highlight, Converter={StaticResource HighlightConverter}}"/>
</Style>
</Style.Resources>
</Style>
</DataGrid.Resources>
</DataGrid>

Categories