DataTemplate binding grid background through a converter - c#

I have a problem for a while with a data binding that changes the color of a grid and somehow it doesn't work.
Iv'e put a break point in the converter and the application hit it, but still the background color of the grid doesn't change and it stays as there is no background color defined...
here is my code:
<ListView ItemsSource="{Binding ResultsUserControls}"
Background="{x:Null}"
BorderBrush="{x:Null}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Width="200"
Height="70"
Background="{Binding CurrentResult,Converter={StaticResource crawlerTypeToResultColorConverter}}">
<Label Content="{Binding .CurrentResult.SourceUrl}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
and the converter:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Brushes.Red;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Binding.DoNothing;
}

I think this should be
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return new SolidColorBrush(Colors.Red);
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return Binding.DoNothing;
}

I've tinkered with your code, and what you have should work. As an experiment, delete CurrentResult from your binding for Background:
<Grid Width="200" Height="70" Background="{Binding Converter={StaticResource crawlerTypeToResultColorConverter}}">
I suspect you will see your red background now. I noticed that if the XAML parser can't find the property that you're binding to (because it's misspelled or just doesn't exist) it won't do the conversion. I would guess that the XAML parser isn't able to find CurrentResult on your items.

Related

Change wpf style from viewmodel

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();
}
}

NullToVisibilityConverter make visible if not null

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}">

binding images in listbox

I have a listbox that is populated from a datatable. I want each item to have a specific image on listbox, but I want to set the image depending of an id that each item has.
for example , I have :
Products
Orange
Apple
ID
1
2
and the images are named: Item.1.png , Item.2.png
So, in my listbox,where I have apple, I will have next to it the image named: Item.2.png.
My problem is that I don't know how could I do a conditional binding . I don't want to have on my template hundreds of lines that are doing this for each item. I need to do this using a condition, like : if(product.id==1), Image.Source=Item.1.png.
Is there any way to do this in wpf?
It sounds to me like you need an IdToImageConverter that will decides which Image should be shown dependant on the value of the Id property. Something like this should do the trick:
[ValueConversion(typeof(int), typeof(ImageSource))]
public class IdToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value.GetType() != typeof(int) || targetType != typeof(ImageSource)) return false;
int id = (int)value;
if (id < 0) return DependencyProperty.UnsetValue;
string imageName = string.Empty;
switch (id)
{
case 1: imageName = "Item.1.png"; break;
case 2: imageName = "Item.2.png"; break;
}
if (imageName.IsEmpty()) return null;
return string.Format("/AppName;component/ImageFolderName/{0}", imageName);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
You could then use it in your ListBox.ItemTemplate something like this:
<YourConvertersXmlNamespacePrefix:IdToImageConverter x:Key="IdToImageConverter" />
...
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Id, Converter={StaticResource
IdToImageConverter}}" />
<TextBlock Text="{Binding Name}" Margin="5,0,0,0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
As I understand your question, every object in the listbox has an ID property, where you want the image to be item.ID.png.
You could use a converter in your binding to do this. So in your listbox template, you can have something like:
// ... Listbox template
<Image Source={Binding pathToItemID, Converter={StaticResource MyConverter}/>
// ... Remaining ListBox template
You will need to add the converter to the UserControl's resources:
<UserControl.Resources>
<xmlnsPointingToConverter:MyConverter x:Key="MyConverter"/>
</UserControl.Resources>
Then add a MyConverter class which implements IValueConverter:
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return string.Format("item.{0}.png", value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

Make converter for columnSpan

I would like to dynamic do the columnSpan on the userControl. I created the converter class, but it didn’t work. Would you show me how to do it correctly? Thanks.
The code on my UserControl:
<TextBlock x:Name="txtSumary" Grid.Row="0" Grid.Column="1" Text="{Binding summary}"
TextWrapping="Wrap" Style="{StaticResource PhoneTextAccentStyle}" Grid.ColumnSpan="{Binding isSpan, Converter={StaticResource ColumSpanConverter}}" />
It is reference on the UserControl.Resources
<local:VisibilityConverter x:Key="ColumSpanConverter"/>
There is the Converter Class:
public class ColumSpanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool isSpan = (bool)value;
return isSpan ? 2 : 0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
The converter is referencing the wrong converter:
<local:VisibilityConverter x:Key="ColumSpanConverter"/>
Should be:
<local:ColumSpanConverter x:Key="ColumSpanConverter" />

Change Binding value in XAML

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}"/>

Categories