I am adding controls to grid rows based on the data type. I have grid in a tab control when I switch the tab away from Grid tab and come back all the controls in the rows are messed up.
Here is my sample code..
Any response will be appreciated.
Presentation Model
using System;using System.Collections.ObjectModel;using System.ComponentModel;using System.Windows.Data;
namespace PropertiesTest{ public class PropertiesPMod : INotifyPropertyChanged { ObservableCollection<Employee> _Employees; private ObservableCollection<PropertyWrapper> _PropertyWrapper;
public PropertiesPMod() { LoadEmployees(); LoadProperties(); }
public ObservableCollection<Employee> Employees { get { return _Employees; } set { _Employees = value; RaisePropertyChanged("Employees"); } }
public ObservableCollection<PropertyWrapper> PropertyWrapper { get { return _PropertyWrapper; } set { _PropertyWrapper = value; RaisePropertyChanged("PropertyWrapper"); } }
private void LoadEmployees() { Employees = new ObservableCollection<Employee>(); Employees.Add(new Employee("Scott", "Meyer")); Employees.Add(new Employee("Chad", "Rust")); Employees.Add(new Employee("Doug", "Rom")); Employees.Add(new Employee("Laxman", "Rawat"));
}
private void LoadProperties() { PropertyWrapper = new ObservableCollection<PropertyWrapper>();
PropertyWrapper.Add(new PropertyWrapper() { Name="Include In-House patients",ExposedValue="True",SqlDataType="bit",Description="In house patient",IsRequired=true,MustSelectFromList=false});
PropertyWrapper.Add(new PropertyWrapper() { Name = "Include InPatient data", ExposedValue = "False", SqlDataType = "bit", Description = "Include inpatient data", IsRequired = true, MustSelectFromList = false });
PropertyWrapper.Add(new PropertyWrapper() { Name = "Include OutPatient patients", ExposedValue = "True", SqlDataType = "bit", Description = "Include outpatient data", IsRequired = true, MustSelectFromList = false });
PropertyWrapper.Add(new PropertyWrapper() { Name = "Start Date", ExposedValue = "12/12/2009", SqlDataType = "Date", Description = "Paient start date", IsRequired = true, MustSelectFromList = false });
PropertyWrapper.Add(new PropertyWrapper() { Name = "End Date", ExposedValue = "12/12/2010", SqlDataType = "Date", Description = "Patient end date", IsRequired = true, MustSelectFromList = false });
PropertyWrapper.Add(new PropertyWrapper() { Name = "physcian Name", ExposedValue = "Laxman", SqlDataType = "varchar", Description = "physcian name", IsRequired = true, MustSelectFromList = false });
PropertyWrapper.Add(new PropertyWrapper() { Name = "Day number", ExposedValue = "1", SqlDataType = "int", Description = "day number", IsRequired = true, MustSelectFromList = false });
PropertyWrapper.Add(new PropertyWrapper() { Name = "week number", ExposedValue = "4", SqlDataType = "int", Description = "week number", IsRequired = true, MustSelectFromList = false }); }
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
#endregion
public class Employee {
private string _FirstName; private string _LastName;
public Employee(string firstName, string lastName) { _FirstName = firstName; _LastName = lastName; }
public string FirstName { get { return _FirstName; } set { _LastName = value; }
public string LastName { get { return _LastName; } set { _LastName = value; }
} public class PropertyWrapper : INotifyPropertyChanged { #region Variables
private string _Message; private string _CodeDescription; private string _ExposedValue; private string _SqlDataType; private string _Value; private bool _IsRequired; private string _Name; private bool _MustSelectFromList; private string _MaxRange; private string _MinRange; private Guid? _CodeDescListID; private string _Description;
#region Properties
public int Sequence { get; set; }
public string Value { get { return _Value; } set { _Value = value; NotifyPropertyChanged("Value"); } }
public string CodeDescription { get { return _CodeDescription; } set { _CodeDescription = value; NotifyPropertyChanged("CodeDescription"); } }
public string ExposedValue { get { return _ExposedValue; } set { _ExposedValue = value;
NotifyPropertyChanged("ExposedValue"); } }
public bool IsRequired { get { return _IsRequired; } set { _IsRequired = value; NotifyPropertyChanged("IsRequired"); } }
public string Name { get { return _Name; } set { _Name = value; NotifyPropertyChanged("Name"); } }
public string SqlDataType { get; set; }
public bool MustSelectFromList { get { return _MustSelectFromList; } set { _MustSelectFromList = value; NotifyPropertyChanged("MustSelectFromList"); } }
public string MaxRange { get { return _MaxRange; } set { _MaxRange = value; NotifyPropertyChanged("MaxRange"); } }
public string MinRange { get { return _MinRange; } set { _MinRange = value; NotifyPropertyChanged("MinRange"); } }
public Guid? CodeDescListID { get { return _CodeDescListID; } set { _CodeDescListID = value; NotifyPropertyChanged("CodeDescListID"); } }
public string Description { get { return _Description; } set { _Description = value; NotifyPropertyChanged("Description"); } }
public int PredefinedFormatId { get; set; }
public int PredefinedFormatPropertyId { get; set; }
public int PredefinedFormatFieldId { get; set; }
public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
} }
public class ComboListStaticResource { private ObservableCollection<string> _ComboList;
public ObservableCollection<string> ComboList { get { return _ComboList; } }
public ComboListStaticResource() { _ComboList = new ObservableCollection<string> { "True", "False" }; } }
#region FormatConverters Members
public class BitFormatter : IValueConverter { public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) { switch ((string)value) { case "-1": return "True"; case "1": return "True"; case "0": return "False"; case "False": case "True": return value; default: return "True"; } }
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) { switch ((string)value) { case "False": return 0; case "True": return -1; default: return 0; } } }
public class IntFormatter : IValueConverter { public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) { return !String.IsNullOrEmpty(System.Convert.ToString(value).Trim()) ? System.Convert.ToDouble((string)value) : (System.Convert.ToString(parameter) == "MaxRange" ? System.Convert.ToDouble("+2,147,483,648") : System.Convert.ToDouble("-2,147,483,648")); }
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value; } }
public class FloatFormatter : IValueConverter {
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) { return !String.IsNullOrEmpty(System.Convert.ToString(value).Trim()) ? System.Convert.ToDouble((string)value) : (System.Convert.ToString(parameter) == "MaxRange" ? System.Convert.ToDouble("+2,147,483,648") : System.Convert.ToDouble("-2,147,483,648")); }
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value; }
public class MustSelectFormatter : IValueConverter {
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) { return (bool)value == false; }
public class MandatoryFormatter : IValueConverter {
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) { return (bool)value ? "*" : ""; }
public class ComboValueConverter : IValueConverter {
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) { var items = new ObservableCollection<string> { "True", "False" }; return items; }
public class DateTimeConverter : IValueConverter { public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value.ToString().ToUpper() == "Now") return DateTime.Now.ToString(); return value; }
View.xaml
<UserControl x:Class="PropertiesTest.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400" xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" xmlns:igGrid="clr-namespace:Infragistics.Controls.Grids;assembly=InfragisticsSL4.Controls.Grids.XamGrid.v10.3" xmlns:ViewModels="clr-namespace:PropertiesTest" xmlns:inputToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit">
<UserControl.Resources>
<ViewModels:MustSelectFormatter x:Key="MustSelectFormatter" /> <ViewModels:DateTimeConverter x:Key="DateTimeConverter" /> <ViewModels:IntFormatter x:Key="IntFormatter" /> <ViewModels:FloatFormatter x:Key="FloatFormatter" /> <ViewModels:BitFormatter x:Key="BitFormatter" /> <ViewModels:MandatoryFormatter x:Key="MandatoryFormatter" /> <ViewModels:ComboValueConverter x:Key="ComboValueConverter" /> <ViewModels:ComboListStaticResource x:Key="ComboList" />
<DataTemplate x:Key="ColMustSelectText"> <TextBox Name="Textbox" Text="{Binding ExposedValue, Mode=TwoWay}" HorizontalContentAlignment="Stretch" IsReadOnly="True"></TextBox> </DataTemplate>
<DataTemplate x:Key="Colcombobox"> <ComboBox ItemsSource="{Binding Path=ComboList, Source={StaticResource ComboList}}" SelectedItem="{Binding Path=Value,Mode=TwoWay,Converter={StaticResource BitFormatter}}" HorizontalContentAlignment="Stretch" Margin="3,0"> </ComboBox> </DataTemplate> <DataTemplate x:Key="ColText"> <TextBox Name="Textbox" Text="{Binding ExposedValue, Mode=TwoWay}" HorizontalContentAlignment="Stretch" IsReadOnly="{Binding Path=MustSelectFromList}" ></TextBox> </DataTemplate> <DataTemplate x:Key="ColDatePicker" > <controls:DatePicker Text="{Binding Path=ExposedValue, Mode=TwoWay,Converter={StaticResource DateTimeConverter}}" HorizontalContentAlignment="Stretch" ></controls:DatePicker> </DataTemplate> <DataTemplate x:Key="ColIntNumericUpdown"> <inputToolkit:NumericUpDown Name="numericUpDown" HorizontalContentAlignment="Stretch" Value="{Binding Path=ExposedValue, Mode=TwoWay}" Maximum="{Binding Path=MaxRange,Converter={StaticResource IntFormatter},ConverterParameter=MaxRange}" Minimum="{Binding Path=MinRange,Converter={StaticResource FloatFormatter},ConverterParameter=MinRange}" IsEditable="{Binding Path=MustSelectFromList,Converter={StaticResource MustSelectFormatter} }" ></inputToolkit:NumericUpDown> </DataTemplate> <DataTemplate x:Key="ColFloatNumericUpdown"> <inputToolkit:NumericUpDown Name="numericUpDown" HorizontalContentAlignment="Stretch" Value="{Binding Path=ExposedValue, Mode=TwoWay}" Maximum="{Binding Path=MaxRange,Converter={StaticResource FloatFormatter},ConverterParameter=MaxRange}" Minimum="{Binding Path=MinRange,Converter={StaticResource FloatFormatter},ConverterParameter=MinRange}" IsEditable="{Binding Path=MustSelectFromList,Converter={StaticResource MustSelectFormatter} }" DecimalPlaces="2" ></inputToolkit:NumericUpDown> </DataTemplate> <DataTemplate x:Key="ColTextBlock"> <TextBlock Name="textBlock" Text="{Binding CodeDescription, Mode=TwoWay}" HorizontalAlignment="Stretch" TextWrapping="Wrap" ScrollViewer.VerticalScrollBarVisibility="Auto"></TextBlock> </DataTemplate>
</UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <controls:TabControl x:Name="tabProperties" Grid.Row="1" Grid.Column="0" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<controls:TabItem Header="Properties">
<igGrid:XamGrid x:Name="reportPropertiesValueGrid" ItemsSource="{Binding PropertyWrapper}" AutoGenerateColumns="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" InitializeRow="reportPropertiesValueGrid_InitializeRow">
<igGrid:XamGrid.Columns> <igGrid:TemplateColumn Key="IsRequired" IsReadOnly="True" Width="SizeToCell" HorizontalContentAlignment="Center" > <igGrid:TemplateColumn.HeaderTemplate> <DataTemplate> <TextBlock Text=""/> </DataTemplate> </igGrid:TemplateColumn.HeaderTemplate> <igGrid:TemplateColumn.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Path=IsRequired,Converter={StaticResource MandatoryFormatter}}" Foreground="Red" ></TextBlock> </DataTemplate> </igGrid:TemplateColumn.ItemTemplate> </igGrid:TemplateColumn> <igGrid:TemplateColumn Key="Name" IsReadOnly="True" Width="Auto" MinimumWidth="250"> <igGrid:TemplateColumn.HeaderTemplate> <DataTemplate> <TextBlock Text="Name"/> </DataTemplate> </igGrid:TemplateColumn.HeaderTemplate> <igGrid:TemplateColumn.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Name,Mode=TwoWay}"></TextBlock> </DataTemplate> </igGrid:TemplateColumn.ItemTemplate> </igGrid:TemplateColumn> </igGrid:XamGrid.Columns> <igGrid:XamGrid.EditingSettings> <igGrid:EditingSettings AllowEditing="Cell" IsMouseActionEditingEnabled="SingleClick" IsOnCellActiveEditingEnabled="True"> </igGrid:EditingSettings> </igGrid:XamGrid.EditingSettings> <igGrid:XamGrid.RowSelectorSettings> <igGrid:RowSelectorSettings EnableRowNumbering="False" Visibility="Collapsed"></igGrid:RowSelectorSettings> </igGrid:XamGrid.RowSelectorSettings> <igGrid:XamGrid.ColumnResizingSettings> <igGrid:ColumnResizingSettings AllowColumnResizing="Indicator"></igGrid:ColumnResizingSettings> </igGrid:XamGrid.ColumnResizingSettings> <igGrid:XamGrid.SelectionSettings> <igGrid:SelectionSettings CellClickAction="SelectRow" RowSelection="Single"></igGrid:SelectionSettings> </igGrid:XamGrid.SelectionSettings>
</igGrid:XamGrid> </controls:TabItem>
<controls:TabItem Header="Raw Properties"> <igGrid:XamGrid x:Name="rawPropertiesGrid" ItemsSource="{Binding PropertyWrapper}" AutoGenerateColumns="true" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<controls:TabItem Header="Other" >
<igGrid:XamGrid x:Name="otherGrid" ItemsSource="{Binding Employees}" AutoGenerateColumns="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" > <igGrid:XamGrid.Columns>
<igGrid:TextColumn Key="FirstName" HeaderText="First Name" Width="50*" /> <igGrid:TextColumn Key="LastName" HeaderText="Last Name" Width="50*" />
</igGrid:XamGrid.Columns>
<igGrid:XamGrid.RowSelectorSettings> <igGrid:RowSelectorSettings Visibility="Collapsed" /> </igGrid:XamGrid.RowSelectorSettings>
<igGrid:XamGrid.SortingSettings> <igGrid:SortingSettings AllowSorting="False" /> </igGrid:XamGrid.SortingSettings>
</igGrid:XamGrid>
</controls:TabItem>
</controls:TabControl>
</Grid></UserControl>
View.cs
using System.Windows;using System.Windows.Controls;using Infragistics.Controls.Grids;
namespace PropertiesTest{ public partial class MainPage : UserControl { private TemplateColumn _TempCol = new TemplateColumn(); private TemplateColumn _TempDescription = new TemplateColumn();
public MainPage() { InitializeComponent(); Model = new PropertiesPMod();
_TempCol.Key = "ExposedValue"; _TempCol.Width = ColumnWidth.Auto; _TempCol.HeaderText = "Value"; _TempCol.MinimumWidth = 130; _TempCol.AllowEditingValidation = true;
_TempDescription.Key = "Description"; _TempDescription.HeaderText = "Description"; _TempDescription.Width = ColumnWidth.Auto; _TempDescription.MinimumWidth = 150; _TempDescription.ItemTemplate = Resources["ColTextBlock"] as DataTemplate;
if (!reportPropertiesValueGrid.Columns.Contains(_TempCol)) reportPropertiesValueGrid.Columns.Add(_TempCol); if (!reportPropertiesValueGrid.Columns.Contains(_TempDescription)) reportPropertiesValueGrid.Columns.Add(_TempDescription);
TemplateColumn templateColumn = (TemplateColumn)reportPropertiesValueGrid.Columns[1]; templateColumn.MinimumWidth = 130;
reportPropertiesValueGrid.UpdateLayout();
public PropertiesPMod Model { get { return this.DataContext as PropertiesPMod; } set { this.DataContext = value; } }
private void reportPropertiesValueGrid_InitializeRow(object sender, InitializeRowEventArgs e) { PropertyWrapper data = (PropertyWrapper)e.Row.Data; if (data == null) return;
//Template should be ColMustSelectText irrespective of the DataType when MustSelectFromList is true if (data.MustSelectFromList && data.SqlDataType.ToLower() != "bit") { _TempCol.ItemTemplate = Resources["ColMustSelectText"] as DataTemplate; } else { switch (data.SqlDataType.ToLower()) { case "date": { _TempCol.ItemTemplate = Resources["ColDatePicker"] as DataTemplate; break; } case "varchar": { _TempCol.ItemTemplate = Resources["ColText"] as DataTemplate; break; } case "float": { _TempCol.ItemTemplate = Resources["ColFloatNumericUpdown"] as DataTemplate; break; } case "int": { _TempCol.ItemTemplate = Resources["ColIntNumericUpdown"] as DataTemplate; break; } case "char": { _TempCol.ItemTemplate = Resources["ColText"] as DataTemplate; break; } case "bit": { _TempCol.ItemTemplate = Resources["Colcombobox"] as DataTemplate; break; } } } } }}
Hi,
I"m not sure how this was working in 10.2.
However, InitRow is only raised the first time a row comes into view. So, as soon as that row goes out of view the control that was used for it will be recycled and attached to another row. If that row was already init'd then it will have a "stale" control in it.
Perhaps, the version of 10.2 had an older version of recycling, which was less efficient and that's why it appeared to work.
However, your better bet would probably be to have some kind of ValueConverter in your DataTemplate, that based on a value of the row, would toggle the visibility of your resources for you.
-SteveZ
can you give me an example please ... I have 5 datatemplate in resource as shown in xaml above.
I don't have a full sample for you, however, here is some pseudo code for the way i might go about it:
Here is the ValueConverter based off of your code, note you'd need to put the DataTemplates in your App.xaml:
public class MyViewValueConverter : IValueConverter { #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { string data = value as string; if (data == null) return null; DataTemplate dt = null; switch (data.ToLower()) { case "date": { dt = Application.Current.Resources["ColDatePicker"] as DataTemplate; break; } case "varchar": { dt = Application.Current.Resources["ColText"] as DataTemplate; break; } case "float": { dt = Application.Current.Resources["ColFloatNumericUpdown"] as DataTemplate; break; } case "int": { dt = Application.Current.Resources["ColIntNumericUpdown"] as DataTemplate; break; } case "char": { dt = Application.Current.Resources["ColText"] as DataTemplate; break; } case "bit": { dt = Application.Current.Resources["Colcombobox"] as DataTemplate; break; } } return dt; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return value; } #endregion }
Then your TemplateColumn would look something like this:
<ig:XamGrid.Columns> <ig:TemplateColumn Key="SqlDataType"> <ig:TemplateColumn.ItemTemplate> <DataTemplate> <ContentControl Content="{Binding}" ContentTemplate="{Binding SqlDataType, Converter={StaticResource myValConverter} }"/> </DataTemplate> </ig:TemplateColumn.ItemTemplate> </ig:TemplateColumn> </ig:XamGrid.Columns>
Hope this helps,
everything seems great but I need to pass 2 values one is SqlDataType which key and also one more property from dto to the converter. Is it possible to do that
Sure.
Just modify the ContentControl to look like this:
<ContentControl Content="{Binding}" ContentTemplate="{Binding Converter={StaticResource myValConverter} }"/>
Now in your ValueConverter, value will be of type : PropertyWrapper instead of type string.
However, now the Binding won't support OneWay/TwoWay bindings. Do you expect either of the 2 properties
that you're checking to change at run time. If not, then this should be fine.
thanks..everything works great.. Although I have one quetsion. Right now I hvae added all the Datatemplate in my UserControl XAML.
So on View's initialize I am adding those to Application resource so that I can access that in my converter. Is there any way it access User controls resource in converter