Unknown attribute Foreground on
element TextBlock
I have this error, when I'm trying to
change the Foreground color depending
on "Read_State"
public class ReadConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool ReadState =(bool)parameter;
if (ReadState == false)
return new SolidColorBrush(Colors.Black);// new SolidColorBrush((Color)Application.Current.Resources["PhoneAccentColor"]);
else
return new SolidColorBrush(Colors.Black);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
In Xaml
<TextBlock Foreground="{Binding Converter={StaticResource ReadConverter},ConverterParameter={Binding Read_State}}" Text="{Binding Path=TexT}" Style="{StaticResource PhoneTextNormalStyle}" TextWrapping="Wrap"/>
The error may just be a bit misleading. You can't use Binding on the ConverterParameter.
You are miss using the converter, you don't need the ConverterParameter at all. Your converter code ought to look like this:-
public class ReadConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool ReadState =(bool)value;
if (ReadState == false)
return new SolidColorBrush(Colors.Black);// new SolidColorBrush((Color)Application.Current.Resources["PhoneAccentColor"]);
else
return new SolidColorBrush(Colors.Black);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
and your Xaml:-
<TextBlock Foreground="{Binding Read_State, Converter={StaticResource ReadConverter}}" Text="{Binding Path=TexT}" Style="{StaticResource PhoneTextNormalStyle}" TextWrapping="Wrap"/>
You might also want to have a read of this blog for future use.
Related
The end goal to be able to set a specific ItemContainerStyle on the first and last element in my list box;
The converters thus far are:
public class IsFirstItemConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool result = false;
result = ((IList<object>)parameter).First() == value;
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class IsLastItemConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool result = false;
result = ((IList<object>)parameter).Last() == value;
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
And implementation:
<DataTrigger Value="True" Binding="{Binding Converter={StaticResource IsFirstItemConverter},ConverterParameter=Items, ElementName=SubItems}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="First"/>
<ContentPresenter/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
And the error is:
InvalidCastException: Unable to cast object of type 'System.String' to
type 'System.Collections.Generic.IList`1[System.Object]'.
Im sure I screwed up in multiple spots, just not experienced enough with XAML and bindings to narrow down where.
The following adapted from the questions comments work perfectly:
public class IsLastItemConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
DependencyObject item = (DependencyObject)value;
ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(item);
return ic.ItemContainerGenerator.IndexFromContainer(item) == ic.Items.Count - 1;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class IsFirstItemConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
DependencyObject item = (DependencyObject)value;
ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(item);
return ic.ItemContainerGenerator.IndexFromContainer(item) == 0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class IsOnlyItemConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
DependencyObject item = (DependencyObject)value;
ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(item);
return (ic.ItemContainerGenerator.IndexFromContainer(item) == 0 && ic.ItemContainerGenerator.Items.Count == 1);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Implementation:
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource IsLastItemConverter}}" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="└"/>
<ContentPresenter/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
The magic seems to be that ItemsControlFromItemContainer makes it so I do not have to pass both the item and its collection instance to the converter but just the item and the converter can infer the parent collection.
I have the following xaml:
<Border x:Name="brdImg3" BorderThickness="2" BorderBrush="Black" Margin="10,5,5,5" Cursor="Hand">
<Image x:Name="image3" Stretch="Fill" Cursor="Hand"/>
</Border>
The problem is, that the Hand-Cursor is only shown when the Source of Image is not null. When the Source is null, the Hand-Cursor is only shown when the Mouse is over the border. I need showing the Hand-Cursor when the Mouse is in the Border. How can I do this?
Use Converter in Cursor, check sources is null or empty. Logic is writen
Cursor={Binding Source,Converter={StaticResources CursorConverter}
public class CursorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (!string.IsNullorEmpty(value.Tostring()))
{
return Cursor.Hand;
}
else
{
return Cursor.Arrow;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
I have this code:
<Rectangle x:Name="cage" Height="247" Canvas.Left="278" Canvas.Top="220" Width="450">
<Rectangle.Fill>
<ImageBrush Stretch="None" ImageSource="resources/cage.gif"/>
</Rectangle.Fill>
</Rectangle>
and
<Label x:Name="to1" Content="1" Canvas.Left="550" Canvas.Top="{Binding Source=cage, Path=Canvas.Top, Mode=OneWay}" BorderBrush="#FF272727" BorderThickness="1" Height="38" Width="38" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="20" PreviewMouseDown="to1_PreviewMouseDown"/>
Binding is working, but I want to maintain locations of this element relative to each other. Another words, if i shift the cage, topProperty of label became "shifting value + 285". How to do this?
Consider using a converter for this purpose as bit suggested.
A simple example should look like this:
XAML
<UserControl.Resources>
<converterNamespace:LabelOffsetConverter x:Key="labelOffsetConverter"/>
</UserControl.Resources>
<Label x:Name="to1" Content="1" Canvas.Left="550"
Canvas.Top="{Binding Source=cage, Path=Canvas.Top, Mode=OneWay,
Converter={StaticResource labelOffsetConverter}"
BorderBrush="#FF272727"
BorderThickness="1"
Height="38" Width="38"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="20" PreviewMouseDown="to1_PreviewMouseDown"/>
Converter Code
public class LabelOffsetConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (!(value is double))
return DependencyProperty.UnsetValue;
double doubleValue = (double)value;
return doubleValue + 285;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// No need to implement, since the binding is in one way mode.
throw new NotImplementedException();
}
}
Solved by this way:
C#
public class Label1offset : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (!(value is double))
return DependencyProperty.UnsetValue;
double doubleValue = (double)value;
return doubleValue + 65.0;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// No need to implement, since the binding is in one way mode.
throw new NotImplementedException();
}
}
Binding binding1 = new Binding();
binding1.Converter = new Label1offset();
binding1.Source = cage;
binding1.Path = new PropertyPath(Canvas.TopProperty);
binding1.Mode = BindingMode.OneWay;
to1.SetBinding(Canvas.TopProperty, binding1);
GoodDay!
I'm not good with wpf and binding, i need your help. I have already bind a Json Object (JObject) to a Column of TextBox.
<TextBox Width="250" Text="{Binding Path=Property, Converter={StaticResource jPropertyConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
I can show properly the data of the Jobject when i start my wpf window, now i need to ConvertBack the data modified when i modify one of the textbox of the columns, from that TextBox to the JObject, and the related JValue.
public class JPropertyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is JProperty)
{
JToken valoreProperty = (value as JProperty).Value;
if ((valoreProperty is JValue))
return (valoreProperty as JValue).Value;
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
??
}
}
I can change the Value of the "leaves" of this JObject tree like:
(valoreProperty as JValue).Value = "Hello!";
How can i change the "leaves" of this JObject tree in the convert back?
Sorry for my english.
Thanks and bye
EDIT:
Thanks dbc! It works, many thanks!
Now i need to show in another column, every lenght of the value inside of the textbox, obviously if i change the value in the texbox the relative lenght value will change too.
I tried:
<DataGridTextColumn Header="Lunghezza2" IsReadOnly="True" Width="50" Binding="{Binding Path=Property.Value.Value.toString().Length, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" />
or in another way with a converter, passing a JProperty
public class LengthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is JProperty)
{
JToken jValue = (value as JProperty).Value;
if ((jValue is JValue) && (jValue as JValue).Value != null)
return (jValue as JValue).Value.ToString().Length.ToString();
else
return "0";
}
else
return "";
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
But every try didn't works when i change the textbox value, any tips?
Many thanks again!
You don't need a converter for this purpose. Assuming your Property property returns a JProperty, you can bind directly to JProperty.Value.Value
<TextBox Name="PropertyTextBox"
Text="{Binding Path=Property.Value.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
/>
If you want to disable the TextBox if the bound Property is not a "simple" JProperty (one with just a JValue for its value), you can do:
<TextBox Name="PropertyTextBox"
Text="{Binding Path=Property.Value.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding Path=Property, Converter={StaticResource IsSimpleJPropertyConverter}, Mode=OneWay}"
/>
Using the converter
public class IsSimpleJPropertyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is JProperty)
{
JToken jValue = (value as JProperty).Value;
if (jValue is JValue)
return true;
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
I'm trying to use a Converter inside a ResourceDictionary. That's the code I have:
<Window x:Class="Metro.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cnv="clr-namespace:Metro.converters">
<Window.Resources>
<cnv:DarkenColorConverter x:Key="Darken" />
<Color x:Key="Red">#FF0000</Color>
<SolidColorBrush Color="{StaticResource Red}"
x:Key="Accent" />
<SolidColorBrush Color="{Binding Source={StaticResource Red}, Converter={StaticResource ResourceKey=Darken}}"
x:Key="DarkAccent" />
</Window.Resources>
<StackPanel>
<Grid Background="{StaticResource Accent}">
<TextBlock>grid 1</TextBlock>
</Grid>
<Grid Background="{StaticResource DarkAccent}">
<TextBlock>grid 2</TextBlock>
</Grid>
</StackPanel>
</Window>
Here's the converter:
public class DarkenColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Brushes.Blue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Brushes.Gray;
}
}
But somehow it's not working. As soon as I use the converter inside the Grid directly, everything works fine:
<Grid Background="{Binding Source={StaticResource Red}, Converter={StaticResource ResourceKey=Darken}}">
<TextBlock>grid 2</TextBlock>
</Grid>
What`s wrong with the first xaml sample?
In the first conversion you are converting a Color, the one in the Grid is converting a SolidColorBrush.
You will have to modify your converter to accept Color also.
public class DarkenColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double percentage = 0.8;
if (parameter != null)
{
double.TryParse(parameter.ToString(), out percentage);
}
if (value is SolidColorBrush)
{
Color color = (value as SolidColorBrush).Color;
return new SolidColorBrush(Color.FromRgb((byte)(color.R * percentage), (byte)(color.G * percentage), (byte)(color.B * percentage)));
}
else if (value is Color)
{
Color color = (Color)value;
return Color.FromRgb((byte)(color.R * percentage), (byte)(color.G * percentage), (byte)(color.B * percentage));
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
The problem was the wrong converter return type.
Working converter:
public class DarkenColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Colors.Blue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Colors.Gray;
}
}