FrameworkElementFactory: Binding doesn't work

Hi,

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

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


Loader.
Up arrow icon