FrameworkElementFactory: Binding doesn't work
Hi,
Attachment: SfGridSample11_7ab9e5b3.zip
I need a SfDataGrid with 4 columns:
column 1: ItemName (not editable)
column 2: ItemShortName (not editable)
column 3: ItemType (editable: 1 or 2 or any other)
column 4: Value (when ItemType==1 it should display ItemName in Readonly-TextBlock, when ItemType==2 it should display ItemShortname in Readonly-TextBox, when ItemType any other value it should display an empty, editable TextBox)
Column 4 should change content after changing ItemType. All requirements have to be defined in code behind.
I've tried to reach the requirements with a DataTrigger based DataTemplate as CellStyle, but Binding doesn't work.
Please find attached simple sample file.
Regards
Harald
Attachment: SfGridSample11_7ab9e5b3.zip
SIGN IN To post a reply.
17 Replies
JG
Jai Ganesh S
Syncfusion Team
January 3, 2017 12:57 PM UTC
Hi Herald,
You can achieve your requirement for updating the Value column based on the ItemType column using CellTemplateSelector like below,
|
private void SampleDataGrid_AutoGeneratingColumn(object sender, AutoGeneratingColumnArgs e)
{
e.Column.AllowEditing = e.Column.MappingName == "ItemType" || e.Column.MappingName == "Value";
if (e.Column.MappingName == "ItemName" || e.Column.MappingName == "ItemShortName" || e.Column.MappingName == "ItemType")
{
e.Column.CellStyle = Application.Current.FindResource("DarkGrayStyle") as Style;
}
if (e.Column.MappingName == "Value")
{
e.Column = new GridTemplateColumn() { MappingName = "Value" };
e.Column.CellTemplateSelector = new DataTemplateSelectorExt();
}
}
public class DataTemplateSelectorExt : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item == null || container == null)
return base.SelectTemplate(item, container);
if ((item as DataItem).ItemType ==1)
{
var factory1 = new FrameworkElementFactory(typeof(TextBlock));
factory1.SetBinding(TextBlock.TextProperty, new Binding("ItemName"));
factory1.SetValue(TextBlock.ForegroundProperty, Brushes.Black);
factory1.SetValue(TextBlock.BackgroundProperty, Brushes.Aquamarine);
return new DataTemplate { VisualTree = factory1 };
}
else if((item as DataItem).ItemType == 2)
{
var factory2 = new FrameworkElementFactory(typeof(TextBox));
factory2.SetBinding(TextBox.TextProperty, new Binding("ItemShortName"));
factory2.SetValue(TextBox.ForegroundProperty, Brushes.Black);
factory2.SetValue(TextBox.IsReadOnlyProperty, true);
factory2.SetValue(TextBox.BackgroundProperty, Brushes.Coral);
return new DataTemplate { VisualTree = factory2 };
}
else
{
var factory3 = new FrameworkElementFactory(typeof(TextBox));
factory3.SetBinding(TextBox.TextProperty, new Binding("ItemShortName"));
factory3.SetValue(TextBox.ForegroundProperty, Brushes.Black);
factory3.SetValue(TextBox.BackgroundProperty, Brushes.Yellow);
return new DataTemplate { VisualTree = factory3 };
}
return base.SelectTemplate(item, container);
}
} |
We have modified your sample based on this and please find the sample from the below location,
Sample: http://www.syncfusion.com/downloads/support/directtrac/general/ze/SfGridSample112030112325.zip
Regards,
Jai Ganesh S
HB
Harald Betzler
January 3, 2017 04:07 PM UTC
Hi Jai,
this works really perfectly.
The important thing is to override the OnUpdateTemplateBinding in GridCellTemplateRenderer. Thank you for the helpful sample.
Regards
Harald
JG
Jai Ganesh S
Syncfusion Team
January 4, 2017 04:12 AM UTC
Hi Herald,
Thank you for the update.
Please let us know if you need further assistance on this.
Regards,
Jai Ganesh S
HB
Harald Betzler
January 6, 2017 08:50 PM UTC
Hi Jai,
the editable TextBoxes now need two mouse clicks to enter edit mode. With keyboard only I generally cannot set them to edit mode.
How can be reached, that the TextBoxes work like regular GridCells (with EditTrigger="OnTap")?
Regards
Harald
JG
Jai Ganesh S
Syncfusion Team
January 9, 2017 10:50 AM UTC
Hi Harald,
You can achieve your requirement to go to edit mode for single click for the template column by setting the FocusedElement like below,
|
factory3.SetValue(Syncfusion.UI.Xaml.Grid.FocusManagerHelper.FocusedElementProperty, true); |
We have modified the sample based on this and please find the sample from below location,
Sample: http://www.syncfusion.com/downloads/support/directtrac/general/ze/SfGridSample111082881517.zip
References:
Regards,
Jai Ganesh S
HB
Harald Betzler
January 9, 2017 08:55 PM UTC
Hi Jai,
thank you for the sample. FocusManagerHelper.FocusedElementProperty works.
Now I need to configure HorizontalAlignment = Right, but then the background color never fills the entire cell but only the width of entered text.
And all the other cells have the following DisplayBinding:
e.Column.DisplayBinding = new Binding(mName) { Converter = new Round2ZeroDigitsConverter(), StringFormat = "N0", ConverterCulture = CultureInfo.CurrentCulture };
But how can it be configured to the TemplateCells via factory?
And finally I discovered, that while starting editing the already entered content isn't selected (like in regular GridCells). How can that be reached?
Regards
Harald
JG
Jai Ganesh S
Syncfusion Team
January 10, 2017 12:13 PM UTC
Hi Harald,
Please find the responses for your queries as below,
Query 1: I need to configure HorizontalAlignment = Right, but then the background color never fills the entire cell but only the width of entered text.
You can set the alignment by setting the HorizontalcontentAlignment property like below,
|
factory2.SetValue(TextBox.HorizontalContentAlignmentProperty,HorizontalAlignment.Right; |
And, for background, we have checked in our side and it fills the entire grid cell only.
Query 2: DisplayBinding
You can set the Displaybinding for GridTemplateColumn in AutoGeneratingcolumn event in your sample. Could you please let us know the purpose to do DisplayBinding for this TemplateColumn . This would help to provide the appropriate solution.
Query 3:
You can select the text while clicking the TemplateColumn cell by using the below code,
|
factory2.AddHandler(TextBox.GotFocusEvent, new RoutedEventHandler(gotFocus));
private void gotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (sender as TextBox);
if (tb != null)
{
tb.Dispatcher.BeginInvoke(new Action(() =>
{
tb.SelectAll();
}), System.Windows.Threading.DispatcherPriority.ApplicationIdle);
}
} |
Sample: http://www.syncfusion.com/downloads/support/directtrac/general/ze/SfGridSample111642044210.zip
Regards,
Jai Ganesh S
HB
Harald Betzler
January 10, 2017 08:41 PM UTC
Hi Jai,
query 1 & 3:
work great.
query 2:
The purpose to use a DisplayBinding is written in forum #127147. Your colleague Sivakumar suggested to realize zero digits in non-editing cells and two digits in cells while editing.
This DisplayBinding works perfectly in regular GridNumericColumns.
Regards
Harald
JG
Jai Ganesh S
Syncfusion Team
January 11, 2017 11:37 AM UTC
Hi Harald,
You can achieve your requirement by creating binding for TextBlock with converter like the below code,
|
factory2.SetBinding(TextBox.TextProperty, new Binding("ItemShortName") { Converter = new NumberRounOffConverter()});
public class NumberRounOffConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//Write your code here
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
} |
Sample: http://www.syncfusion.com/downloads/support/directtrac/general/ze/SfGridSample11-751570143.zip
Regards,
Jai Ganesh S
HB
Harald Betzler
January 11, 2017 12:20 PM UTC
Hi Jai,
the converter works now. Thank you.
But there's another difference.
In regular GridNumericColumn:
- After entering e.g. "123.45" and leaving the cell, the cell displays "123".
- When entering the cell again and starting editing, there is shown "123.45" again.
With the same converter in GridTemplateColumn I can't se the "123.45" again after reentering the cell. There still remain "123".
What can I do to get the same behavior like GridNumericColumn?
Regards
Harald
JG
Jai Ganesh S
Syncfusion Team
January 12, 2017 12:48 PM UTC
Hi Harald,
In your sample, you have loaded the TextBlock and TextBox inside the CellTemplateSelector. Hence you cannot achieve this requirement like in a GridNumericColumn. However, you can achieve this requirement by loading the TextBlock inside the CellTemplateSelector and load the TextBox inside the EditTemplateSelector.
Regards,
Jai Ganesh S
HB
Harald Betzler
January 12, 2017 11:27 PM UTC
Hi Jai,
sorry, I really do not want to annoy you, but I'm extremely frustrated.
To fulfill a little bit complex requirements it will take many days or weeks. Every time a small step is done at least one new problem occurs.
I've tried a lot of things with DataTemplateSelector and EditTemplateSelector, with Converters and MultiBindingConverters. I'm about to give up.
I had a grid with GridNumericColumns and the typical behavior. Then - to realize some locked cells - I have to implement a DataTemplateSelector. Ok, the expected cells are locked. But nothing else is like the GridNumericColumn - alignment, formats, edit mode, colors, borders...
I have to implement an EditTemplateSelector and there was a bunch of new problems.
This approach is not really constructive.
Syncfusion is actually not very new on market. Is there really no implementation of a simple requirement (like locked cells) without loosing the complete regular behavior?
I'm really afraid of implementing the next requirement - number format with different number of digits after the decimal depending on a integer property "DigitNumber" of the ItemsSource.
Please excuse the harassment. But I've never had such problems while using Telerik controls in the past. The free community license is really a great idea, but not with attendant loss of productivity.
Frustrated regards
Harald
SR
Sivakumar R
Syncfusion Team
January 13, 2017 09:43 AM UTC
Hi Harald,
Your requirement can be achieve by handling GotFocus and LostFocus events of editable TextBox in the template. I have modified the sample to achieve your requirement. Please find the code snippet and sample below,
|
public class DataTemplateSelectorExt : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item == null || container == null)
return base.SelectTemplate(item, container);
if ((item as DataItem).ItemType == 1)
{
var factory1 = new FrameworkElementFactory(typeof(TextBlock));
factory1.SetBinding(TextBlock.TextProperty, new Binding("ItemName"));
factory1.SetValue(TextBlock.ForegroundProperty, Brushes.Black);
factory1.SetValue(TextBlock.BackgroundProperty, Brushes.Aquamarine);
return new DataTemplate { VisualTree = factory1 };
}
else if ((item as DataItem).ItemType == 2)
{
var factory2 = new FrameworkElementFactory(typeof(TextBox));
factory2.SetBinding(TextBox.TextProperty, new Binding("ItemShortName"));
factory2.SetValue(TextBox.ForegroundProperty, Brushes.Black);
factory2.SetValue(TextBox.IsReadOnlyProperty, true);
factory2.SetValue(TextBox.HorizontalContentAlignmentProperty, HorizontalAlignment.Right);
factory2.SetValue(Syncfusion.UI.Xaml.Grid.FocusManagerHelper.FocusedElementProperty, true);
factory2.SetValue(TextBox.BackgroundProperty, Brushes.Coral);
factory2.AddHandler(TextBox.GotFocusEvent, new RoutedEventHandler(ReadOnlyTextBox_GotFocus));
return new DataTemplate { VisualTree = factory2 };
}
else
{
var factory3 = new FrameworkElementFactory(typeof(TextBox));
factory3.SetBinding(TextBox.TextProperty, new Binding("Value") { Converter = new NumberRounOffConverter() });
factory3.SetValue(TextBox.ForegroundProperty, Brushes.Black);
factory3.SetValue(TextBox.HorizontalContentAlignmentProperty, HorizontalAlignment.Right);
factory3.SetValue(Syncfusion.UI.Xaml.Grid.FocusManagerHelper.FocusedElementProperty, true);
factory3.SetValue(TextBox.BackgroundProperty, Brushes.Yellow);
factory3.AddHandler(TextBox.GotFocusEvent, new RoutedEventHandler(EditTextBox_GotFocus));
factory3.AddHandler(TextBox.LostFocusEvent, new RoutedEventHandler(EditTextBox_LostFocus));
return new DataTemplate { VisualTree = factory3 };
}
return base.SelectTemplate(item, container);
}
//To display value with decimal digits when focusing.
private void EditTextBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (sender as TextBox);
tb.SetBinding(TextBox.TextProperty, new Binding("Value"));
tb.Dispatcher.BeginInvoke(new Action(() =>
{
tb.SelectAll();
}), System.Windows.Threading.DispatcherPriority.ApplicationIdle);
}
//To display value by rounding off after editing
private void EditTextBox_LostFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (sender as TextBox);
tb.SetBinding(TextBox.TextProperty, new Binding("Value") { Converter = new NumberRounOffConverter() });
}
private void ReadOnlyTextBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (sender as TextBox);
tb.Dispatcher.BeginInvoke(new Action(() =>
{
tb.SelectAll();
}), System.Windows.Threading.DispatcherPriority.ApplicationIdle);
}
} |
Here, When you focus the TextBox only it will display the value with decimal digits. Otherwise, it will display the round-off values only.
Sample:
Thanks,
Sivakumar
HB
Harald Betzler
January 16, 2017 04:04 AM UTC
Hi Sivakumar,
thank you for the solution.
Unfortunately an entered number can't be deleted any more. Do you know why?
Regards
Harald
JG
Jai Ganesh S
Syncfusion Team
January 18, 2017 12:56 PM UTC
Hi Harald,
You can achieve your requirement by calling the converter in GotFocus event of TextBox like below,
|
private void EditTextBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (sender as TextBox);
tb.Dispatcher.BeginInvoke(new Action(() =>
{
tb.SetBinding(TextBox.TextProperty, new Binding("Value") { Converter = new NullConverter()});
tb.SelectAll();
}), System.Windows.Threading.DispatcherPriority.ApplicationIdle);
}
public class NullConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return string.Empty;
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return value;
if (string.IsNullOrEmpty(value.ToString()))
return null;
return value;
}
}
|
Sample: http://www.syncfusion.com/downloads/support/directtrac/general/ze/WpfTestingSample-1795358397.zip
Regards,
Jai Ganesh S
HB
Harald Betzler
January 19, 2017 08:42 PM UTC
Hi Jai,
thank you. You made my day.
Regards
Harald
JG
Jai Ganesh S
Syncfusion Team
January 20, 2017 01:16 AM UTC
Hi Harald,
Thank you for the update.
Please let us know if you need further assistance on this.
Regards,
Jai Ganesh S
SIGN IN To post a reply.
- 17 Replies
- 3 Participants
-
HB Harald Betzler
- Jan 2, 2017 05:15 AM UTC
- Jan 20, 2017 01:16 AM UTC