StringFormat doesnt change number in Silverlight <telerik:GridViewDataColumn> - silverlight

I want numbers like 123456 becomes like 123,456.
so in here:
<telerik:GridViewDataColumn DataMemberBinding="{Binding value}" Header="sth" />
I added stringformat. None of below didn't work out:
<telerik:GridViewDataColumn DataMemberBinding="{Binding value, StringFormat=\{0:N2\}}" Header="sth" />
<telerik:GridViewDataColumn DataMemberBinding="{Binding value, StringFormat='{}{0:N0}'}" Header="sth" />
<telerik:GridViewDataColumn DataMemberBinding="{Binding value, StringFormat='###,###'}" Header="sth" />
<telerik:GridViewDataColumn DataMemberBinding="{Binding value, StringFormat=\{0:N0\}" Header="sth" />
<telerik:GridViewDataColumn DataMemberBinding="{Binding Value,StringFormat=\{0:N\}}" "sth" DataFormatString="{}{0:N0}"/>
number shows up like 123456, no changes happening

The format StringFormat='###,###' is not valid syntax for XAML string format. To have it correctly, you should have an argument passed somewhere ({0..}).
Try the following to have the desired behavior:
<telerik:GridViewDataColumn DataMemberBinding="{Binding Item, StringFormat={}{0:###,0}}" />

You can create a class like this:
public class SFMoneyColumn : GridViewBoundColumnBase
{
public override FrameworkElement CreateCellEditElement(GridViewCell cell, object dataItem)
{
var cellEditElement = new SFMoney();
// cellEditElement.Mask = Mask;
// cellEditElement.EmptyContent = EmptyContent;
// cellEditElement.SelectedDateFormat = DatePickerFormat.Short;
// cellEditElement.SelectedDateChanged += new EventHandler<System.Windows.Controls.SelectionChangedEventArgs>(cellEditElement_SelectedDateChanged);
// this.BindingTarget = DatePicker.SelectedDateProperty;
Binding valueBinding = this.CreateValueBinding(false);
cellEditElement.SetBinding(SFMoney.ValueProperty, valueBinding);
return cellEditElement as FrameworkElement;
}
public override FrameworkElement CreateCellElement(GridViewCell cell, object dataItem)
{
var cellElement = new Telerik.Windows.Controls.Label();
//var cellElement = new SFMoney();
// cellElement.IsReadOnly = true;
Binding valueBinding = this.CreateValueBinding(true);
valueBinding.Mode = BindingMode.OneWay;
// cellElement.SetBinding(SFMoney.ValueProperty, valueBinding);
cellElement.SetBinding(Telerik.Windows.Controls.Label.ContentProperty, valueBinding);
return cellElement;
}
private Binding CreateValueBinding(bool converter)
{
Binding valueBinding = new Binding();
valueBinding.Mode = BindingMode.TwoWay;
valueBinding.NotifyOnValidationError = true;
valueBinding.ValidatesOnExceptions = true;
if (converter)
valueBinding.Converter = new SFMoneyConverter();
// valueBinding.UpdateSourceTrigger = UpdateSourceTrigger.Default;
valueBinding.Path = new PropertyPath(this.DataMemberBinding.Path.Path);
return valueBinding;
}
public string DataMemberPath { set; get; }
// public SFColumn SFColumn { set; get; }
}
public class SFMoneyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null)
{
string ashar = "";
string val = value.ToString();
if (val.Contains("."))
{
ashar = val.Substring(val.IndexOf("."), val.Length - val.LastIndexOf("."));
value = Math.Floor(System.Convert.ToDouble(value));
}
string str = String.Format("{0:0,0}", value) + ashar;
// string str = String.Format("{0:0,0}", value);
if (str.StartsWith("0"))
str = str.Remove(0, 1);
return str;
}
else
return "";
// return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//return (value as EnumComboItem).SelectedItem;
return null;
}
}
And then use it in your Grid
<sfx:SFMoneyColumn DataMemberBinding="{Binding Price}" UniqueName="Price" Header="مبلغ کارشناسي" />

Related

How do I bind ARGB values to a rectangle fill property in a combo box item?

I have a combobox of custom objects each of which is displayed as a colored rectangle and beside it a text.
I have the ARGB values I want to display from the object, but I want to convert that to a color and set it to the fill property of the rectangle. So far I have the following based on this post
Binding R G B properties of color in wpf
How do you specify which propertied in SubCategory to pass to the value converter? And how to set the result of the converter to the Fill property of the rectangle?
//XAML
<Controls:MetroWindow.Resources>
<local:ArgbConverter x:Key="argbConverter"></local:ArgbConverter>
</Controls:MetroWindow.Resources>
<ComboBox ItemsSource="{Binding Path=SubCategories}" HorizontalAlignment="Stretch" SelectedItem="{Binding Path=SelectedSubCategory, Mode=TwoWay}" IsEditable="False" TextBoxBase.TextChanged="SubCategory_ComboBox_TextChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="Aqua" Width="16" Height="16" Margin="0,2,5,2" ></Rectangle>
<TextBlock Text="{Binding Path=name, Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
//Value Converter
public class ArgbConverter : IMultiValueConverter
{
#region IMultiValueConverter Members
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var a = System.Convert.ToByte(values[0]);
var r = System.Convert.ToByte(values[1]);
var g = System.Convert.ToByte(values[2]);
var b = System.Convert.ToByte(values[3]);
return new Color() { A = a, B = b, R = r, G = g };
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
//VIEWMODEL
public ObservableCollection<SubCategory> SubCategories { get; set; } = new ObservableCollection<SubCategory>() { new SubCategory() { name = "person" } };
//SubCategory class
public class SubCategory
{
//default values - each of these objects will have different argb values
public int A { get; set; } = 95;
public int R { get; set; } = 225;
public int G { get; set; } = 80;
public int B { get; set; } = 25;
public string name { get; set; }
}
Why can't you use IValueConverter instead of IMultiValueConverter?
XAML
<Rectangle Fill="{Binding Path=., Converter={StaticResource argbConverter}}"
Width="16" Height="16"/>
Converter
public class ArgbConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var item = value as SubCategory;
var a = System.Convert.ToByte(item.A);
var r = System.Convert.ToByte(item.R);
var g = System.Convert.ToByte(item.G);
var b = System.Convert.ToByte(item.B);
return new SolidColorBrush(new Color() { A = a, B = b, R = r, G = g });
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
You have already implemented an IMultiValueConverter. So the obvious answer seems to be a MultiBinding, with four Bindings to the A, R, G and B properties:
<Rectangle>
<Rectangle.Fill>
<SolidColorBrush>
<SolidColorBrush.Color>
<MultiBinding Converter="{StaticResource argbConverter}">
<Binding Path="A"/>
<Binding Path="R"/>
<Binding Path="G"/>
<Binding Path="B"/>
</MultiBinding>
</SolidColorBrush.Color>
</SolidColorBrush>
</Rectangle.Fill>
</Rectangle>

Conditional data validation in wpf

I have 3 radio buttons and a text box.
See the image for UI
When user selects 'Phone' radio button I should allow to enter only numbers in the textbox, similarly the other cases email and name.
Email should be in correct format. and name should start with character.
How to do this in wpf?
Please try the next:
The TextBox code
<TextBox x:Name="TextBoxWithValidation" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Text="{Binding Text, UpdateSourceTrigger=LostFocus, Mode=TwoWay,
NotifyOnValidationError=True, ValidatesOnDataErrors=True}">
<Validation.ErrorTemplate>
<ControlTemplate>
<DockPanel>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder x:Name="ControlWithError"/>
</Border>
<ContentControl x:Name="ValidationSymbol" Margin="-10,0,0,0" Content="{Binding ElementName=ControlWithError,
Path=AdornedElement.(Validation.Errors), Converter={wpfValidationIssueHelpAttempt:Errors2ValidationErrorContentConverter},
UpdateSourceTrigger=PropertyChanged}" ContentTemplate="{StaticResource CommonValidationSymbol}"/>
</DockPanel>
</ControlTemplate>
</Validation.ErrorTemplate>
</TextBox>
The converter code:
public class Errors2ValidationErrorContentConverter : MarkupExtension, IValueConverter
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var errors = value as ReadOnlyCollection<ValidationError>;
ValidationError error;
if (errors == null || (error = errors.FirstOrDefault()) == null) return null;
return error.ErrorContent.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
The validation symbol code(put this to the resource section):
<DataTemplate x:Key="CommonValidationSymbol">
<TextBlock Panel.ZIndex="1000" Foreground="Red" FontFamily="Segoe UI" FontWeight="Bold"
Width="10"
FontSize="15" Background="#0000FF00" Text="!">
<ToolTipService.ToolTip>
<ToolTip x:Name="validationTooltip" Content="{Binding }" Placement="Right"/>
</ToolTipService.ToolTip>
</TextBlock>
</DataTemplate>
Here is my DataContext code
public class MainViewModel:BaseObservableObject, IDataErrorInfo
{
private string _text;
private string _error;
private bool _isMailChecked;
private bool _isNameChecked;
private bool _isPhoneChecked;
public virtual string Text
{
get { return _text; }
set
{
_text = value;
OnPropertyChanged(() => Text);
}
}
public string this[string columnName]
{
get
{
if (columnName == "Text")
{
if (string.IsNullOrEmpty(Text)) return string.Empty;
Error = string.Empty;
return GetValidationResult();
}
return String.Empty;
}
}
private string GetValidationResult()
{
//define your logic here
if (IsNameChecked)
{
Error = "name is wrong!";
}
if (IsMailChecked)
{
Error = "mail is wrong!";
}
if (IsPhoneChecked)
{
Error = "phone is wrong";
}
return Error;
}
public string Error
{
get { return _error; }
private set
{
_error = value;
OnPropertyChanged(() => Error);
}
}
public bool IsNameChecked
{
get { return _isNameChecked; }
set
{
_isNameChecked = value;
OnPropertyChanged(() => IsNameChecked);
if (value == false) return;
IsMailChecked = false;
IsPhoneChecked = false;
Text = String.Empty;
}
}
public bool IsMailChecked
{
get { return _isMailChecked; }
set
{
_isMailChecked = value;
OnPropertyChanged(() => IsMailChecked);
if (value == false) return;
IsNameChecked = false;
IsPhoneChecked = false;
Text = String.Empty;
}
}
public bool IsPhoneChecked
{
get { return _isPhoneChecked; }
set
{
_isPhoneChecked = value;
OnPropertyChanged(() => IsPhoneChecked);
if (value == false) return;
IsMailChecked = false;
IsNameChecked = false;
Text = String.Empty;
}
}
}
Regards.

Want to display "Yes"/"No" in a dynamically generated column for Boolean value instead of checkbox in RadGridView for WPF

I would like to display "Yes" or "No" for whenever a Boolean type data received(it can receive different types of data) for generating a column in RadGridView instead of a checkbox. I would like to implement this changes in xaml. Columns are generating dynamically. This is how it's created now:
<telerik:RadGridView x:Name="Data" Grid.Row="3" Margin="5" AutoGenerateColumns="False" CanUserSortColumns="True" IsFilteringAllowed="True"
grid:RadGridViewColumnsBinding.ColumnsCollection="{Binding Path=ColumnsData}"
IsReadOnly="False" CanUserResizeColumns="True"/>
I am new in Silverlight coding. Will really appreciate if someone can help.
You should check out Telerik's ConditionalDataTemplateSelector they have in this demo, and read about IValueConverter if you haven't already.
Depending on what you are trying to do with all your columns, the ConditionalDataTemplateSelector might be overkill, but you can use it to create a rule system for what DataTemplate to use for a given cell based on a custom rule system.
<Grid.Resources>
...
<DataTemplate x:Key="CellDisplayTextBox">
<TextBlock Text="{Binding Value, Converter={StaticResource BooleanToYesNoConverter}}" />
</DataTemplate>
<selector:ConditionalDataTemplateSelector x:Key="displaySelector" ConditionConverter="{StaticResource someConverter}">
<selector:ConditionalDataTemplateSelector.Rules>
<selector:ConditionalDataTemplateRule DataTemplate="{StaticResource CellDisplayTextBox}">
<selector:ConditionalDataTemplateRule.Value>
<sys:Int32>1</sys:Int32> <!--You need to figure out what value and type to use here -->
</selector:ConditionalDataTemplateRule.Value>
</selector:ConditionalDataTemplateRule>
...
</selector:ConditionalDataTemplateSelector.Rules>
</Grid.Resources>
...
<telerikGridView:RadGridView>
<telerik:RadGridView.Columns>
<telerik:GridViewDataColumn CellTemplateSelector="{StaticResource displaySelector}" CellEditTemplateSelector="{StaticResource editSelector}" />
</telerik:RadGridView.Columns>
</telerikGridView:RadGridView>
The IValueConverter will let you bind a bool value, but display a string value. For a BooleanToYesNoConverter you could do something like:
public class BooleanToYesNoConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool? bValue = value as bool?;
if (bValue.HasValue)
return bValue.Value ? "Yes" : "No";
else
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
string sValue = value as string;
return sValue == "Yes";
}
}
The ConditionalDataTemplateSelector code from the demo:
public class ConditionalDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
object conditionValue = this.ConditionConverter.Convert(item, null, null, null);
foreach (ConditionalDataTemplateRule rule in this.Rules)
{
if (Equals(rule.Value, conditionValue))
{
return rule.DataTemplate;
}
}
return base.SelectTemplate(item, container);
}
List<ConditionalDataTemplateRule> _Rules;
public List<ConditionalDataTemplateRule> Rules
{
get
{
if (this._Rules == null)
{
this._Rules = new List<ConditionalDataTemplateRule>();
}
return this._Rules;
}
}
IValueConverter _ConditionConverter;
public IValueConverter ConditionConverter
{
get
{
return this._ConditionConverter;
}
set
{
this._ConditionConverter = value;
}
}
}
public class ConditionalDataTemplateRule
{
object _Value;
public object Value
{
get
{
return this._Value;
}
set
{
this._Value = value;
}
}
DataTemplate _DataTemplate;
public DataTemplate DataTemplate
{
get
{
return this._DataTemplate;
}
set
{
this._DataTemplate = value;
}
}
}

WPF converter and dictionary

How do you properly implement a IValueConverter if you have a dictionary populated in another class?
I'm sure i'm doing something wrong here but to explain my problem properly, here are the code supporting the question.
iPresenter_IconLists.cs
public interface iPresenter_IconLists
{
Dictionary<string, IconPositionDetails> IconDetails { get; set; }
}
Presenter_IconLists.cs
public class Presenter_IconLists : iPresenter_IconLists, IValueConverter
{
public Presenter_IconLists()
{
}
public void PopulateDictionaryTest()
{
this.IconDetails.Add("test1", new IconPositionDetails()
{
x = 0,
y = 0
});
this.IconDetails.Add("test2", new IconPositionDetails()
{
x = 0,
y = 0
});
this.IconDetails.Add("test3", new IconPositionDetails()
{
x = 0,
y = 0
});
}
Dictionary<string, IconPositionDetails> _IconDetails = new Dictionary<string, IconPositionDetails>();
public Dictionary<string, IconPositionDetails> IconDetails
{
get { return this._IconDetails; }
set { this._IconDetails = value; }
}
// IValueConverter implementation
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
iPresenter_IconLists i = this;
IconPositionDetails ipd = i.IconDetails[value.ToString()];
// or
// IconPositionDetails ipd = this.IconDetails[value.ToString()];
return string.Format("x: {0}, y: {1}", ipd.x, ipd.y);
}
}
MainWindow.xaml
<Window.Resources>
<l:Presenter_IconLists x:Key="DictConvert" x:Name="DictConvert" />
<TextBlock Text="{Binding Converter={StaticResource DictConvert}, ConverterParameter=Value.x}" Height="28" HorizontalAlignment="Left" Margin="60,49,0,0" VerticalAlignment="Top" FontSize="11" />
</Window.Resources>
MainWindow.xaml.cs
Presenter_IconLists iconlists;
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
this.iconlists = new Presenter_IconLists();
this.iconlists.PopulateDictionaryTest();
lbIcons.ItemsSource = this.iconlists.IconDetails;
}
the problem here is, I always getting "The given key was not present in the dictionary." and when I check the this.IconDetails number of collection, it was zero.
How do I access my dictionary inside the Converter?
Your constructor doesn't add items to the dictionary, so there are no items in it. When you go to convert, the dictionary is empty.
You need to, at some point, populate the dictionary with values. This is not happening, as the dictionary is created by WPF (<l:Presenter_IconLists x:Key="DictConvert" />) and never has values added to it.
you use converter Parameter instead of Path in binding.
use Path in binding:
<DataTemplate x:Key="lbItems" x:Name="lbItems">
<TextBlock Text="{Binding Path=Value.name, Converter={StaticResource DictConvert}}" />
</DataTemplate>
or use parameter in Convert function:
IconPositionDetails ipd = i.IconDetails[parameter.ToString()];

Bind a Silverlight TabControl to a Collection

I have a Collection of Model-objects in my ViewModel. I would like to be able to bind a TabControl to these and use a DataTemplate to extract the information from the Model-objects. When I try to do this I get the errormessage: Unable to cast object of type Model to object of type TabItem. After spending some time looking for a solution I found the following:
The Silverlight TabControl is
broken. Use a combination of ListBox
and ContentControl to mimic the
behaviour of a TabControl. (Means
that I have to skin the ListBox to
look like a TabControl)
TabControl does not override
PrepareContainerForItemOverride and
the solution is to make a
Converter. (Not so good because I
then need to specify the type of the
convertee in the Converter)
Anyone know any better solution?
XAML
<sdk:TabControl ItemsSource="{Binding Items, ElementName=MyControl}">
<sdk:TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</sdk:TabControl.ItemTemplate>
</sdk:TabControl>
C#
public ObservableCollection<Model> Items { get; set; }
public ViewModel()
Items = new ObservableCollection<Model>{
new Model { Name = "1"},
new Model { Name = "2"},
new Model { Name = "3"},
new Model { Name = "4"}
};
}
Suggested Converter:
public class TabConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
List<TabSource> source = value as List<TabSource>;
if (source != null)
{
List<TabItem> result = new List<TabItem>();
foreach (TabSource tab in source)
{
result.Add(new TabItem()
{
Header = tab.Header,
Content = tab.Content
});
}
return result;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Create converter
public class SourceToTabItemsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
var source = (IEnumerable)value;
if (source != null)
{
var controlTemplate = (ControlTemplate)parameter;
var tabItems = new List<TabItem>();
foreach (object item in source)
{
PropertyInfo[] propertyInfos = item.GetType().GetProperties();
//тут мы выбираем, то поле которое будет Header. Вы должны сами вводить это значение.
var propertyInfo = propertyInfos.First(x => x.Name == "name");
string headerText = null;
if (propertyInfo != null)
{
object propValue = propertyInfo.GetValue(item, null);
headerText = (propValue ?? string.Empty).ToString();
}
var tabItem = new TabItem
{
DataContext = item,
Header = headerText,
Content =
controlTemplate == null
? item
: new ContentControl { Template = controlTemplate }
};
tabItems.Add(tabItem);
}
return tabItems;
}
return null;
}
catch (Exception)
{
return null;
}
}
/// <summary>
/// ConvertBack method is not supported
/// </summary>
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException("ConvertBack method is not supported");
}
Create ControlTemplate:
<ControlTemplate x:Key="MyTabItemContentTemplate">
<StackPanel>
<TextBlock Text="{Binding Path=name}" />
</StackPanel>
</ControlTemplate>
And binding convert, controltemplate
<controls:TabControl x:Name="tabControl"
ItemsSource="{Binding ElementName=tabControl,
Path=DataContext,
Converter={StaticResource ConverterCollectionToTabItems},
ConverterParameter={StaticResource MyTabItemContentTemplate}}">
</controls:TabControl>
taken from the blog binding-tabcontrol

Resources