We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

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