Home Forums WPF controls Xceed DataGrid for WPF Resource Not Found Exceptions

Viewing 15 posts - 16 through 30 (of 34 total)
  • Author
    Posts
  • User (Old forums)
    Member
    Post count: 23064

    Sorry ignore that last comment

    What I meant was the if I set a breakpoint in the “getter” of my Single property, it is not called until I click on the next row, even though the RaisePropertyChanged is called whenever the TextBox in my editor is updated

    Imported from legacy forums. Posted by nmosafi (had 475 views)

    User (Old forums)
    Member
    Post count: 23064

    I see from the code you posted earlier that most of your Columns are bound to Property.SubProperty, could you give me an idea of the structure of YieldFactDataModel?

    Sorry for the series of questions, but I cannot reproduce the problem on my side and I really want to nail this problem down…

    Imported from legacy forums. Posted by Pascal (had 220 views)

    User (Old forums)
    Member
    Post count: 23064

    I think what would be easier would be if I try to reproduce the error using a small project and send you the code, as we have some big model classes that we are databinding to.

    I will let you know when I have an isolated test case.

    Thanks
    Neil

    Imported from legacy forums. Posted by nmosafi (had 353 views)

    User (Old forums)
    Member
    Post count: 23064

    That would help a lot, thanks! 😀

    Imported from legacy forums. Posted by Pascal (had 1086 views)

    User (Old forums)
    Member
    Post count: 23064

    OK here is some code which duplicates the problem. The issue is that the values aren’t updated until the selected item is changed to another row, rather than another cell.

    Here is the XAML file

    <Window x:Class=”TestXceed.Window1″
    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml&#8221;
    xmlns:xcd=”clr-namespace:Xceed.Wpf.Controls;assembly=Xceed.Wpf.Controls”
    xmlns:xcdg=”http://schemas.xceed.com/wpf/xaml/datagrid&#8221;
    xmlns:local=”clr-namespace:TestXceed”
    Title=”TestXceed” Height=”300″ Width=”300″
    >
    <Window.Resources>
    <local:FormattingConverter x:Key=”FormattingConverter” />
    </Window.Resources>

    <Grid>

    <xcdg:DataGridControl ItemsSource=”{x:Static local:Window1.YieldFacts}” AutoCreateColumns=”False”>
    <xcdg:DataGridControl.Columns>
    <xcdg:Column FieldName=”SingleYield” Title=”Single Yield” DisplayMemberBinding=”{Binding Path=SingleValue, Mode=TwoWay, Converter={StaticResource FormattingConverter}, ConverterParameter=[0:£0.00]}” Width=”80″>
    <xcdg:Column.CellEditor>
    <xcdg:CellEditor>
    <xcdg:CellEditor.EditTemplate>
    <DataTemplate>
    <xcd:AutoSelectTextBox Text=”{Binding RelativeSource={RelativeSource AncestorType={x:Type xcdg:DataCell}}, UpdateSourceTrigger=PropertyChanged, Path=DataContext.SingleValue, Converter={StaticResource FormattingConverter}, ConverterParameter=[0:0.00]}” />
    </DataTemplate>
    </xcdg:CellEditor.EditTemplate>
    <xcdg:CellEditor.ActivationGestures>
    <xcdg:TextInputActivationGesture />
    </xcdg:CellEditor.ActivationGestures>
    </xcdg:CellEditor>
    </xcdg:Column.CellEditor>
    </xcdg:Column>
    <xcdg:Column FieldName=”ReturnYield” Title=”Return Yield” DisplayMemberBinding=”{Binding Path=ReturnValue, Mode=TwoWay, Converter={StaticResource FormattingConverter}, ConverterParameter=[0:£0.00]}” Width=”80″>
    <xcdg:Column.CellEditor>
    <xcdg:CellEditor>
    <xcdg:CellEditor.EditTemplate>
    <DataTemplate>
    <xcd:AutoSelectTextBox Text=”{Binding RelativeSource={RelativeSource AncestorType={x:Type xcdg:DataCell}}, UpdateSourceTrigger=PropertyChanged, Path=DataContext.ReturnValue, Converter={StaticResource FormattingConverter}, ConverterParameter=[0:0.00]}” />
    </DataTemplate>
    </xcdg:CellEditor.EditTemplate>
    <xcdg:CellEditor.ActivationGestures>
    <xcdg:TextInputActivationGesture />
    </xcdg:CellEditor.ActivationGestures>
    </xcdg:CellEditor>
    </xcdg:Column.CellEditor>
    </xcdg:Column>
    </xcdg:DataGridControl.Columns>

    <xcdg:DataGridControl.View>
    <xcdg:TableView ShowRowSelectorPane=”False”>
    <xcdg:TableView.FixedHeaders>
    <xcdg:ClearHeadersFooters />
    <DataTemplate>
    <xcdg:ColumnManagerRow Width=”{Binding RelativeSource={RelativeSource AncestorType={x:Type ScrollContentPresenter}}, Path=ActualWidth}” />
    </DataTemplate>
    </xcdg:TableView.FixedHeaders>
    </xcdg:TableView>
    </xcdg:DataGridControl.View>

    </xcdg:DataGridControl>

    </Grid>

    </Window>

    And here is the C# file

    using System;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Data;

    namespace TestXceed
    {
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
    public Window1()
    {
    InitializeComponent();
    }

    public static YieldFact[] YieldFacts
    {
    get
    {
    return new YieldFact[] { new YieldFact(), new YieldFact(), new YieldFact(), new YieldFact() };
    }
    }
    }

    public class YieldFact : INotifyPropertyChanged
    {
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
    if (PropertyChanged != null)
    {
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    }

    private decimal? singleValue;
    private decimal? returnValue;

    public decimal? SingleValue
    {
    get { return NormalizeValue(singleValue); }
    set
    {
    this.singleValue = NormalizeValue(value);
    RaisePropertyChanged(“SingleValue”);
    }
    }

    public decimal? ReturnValue
    {
    get { return NormalizeValue(returnValue); }
    set
    {
    this.returnValue = NormalizeValue(value);
    RaisePropertyChanged(“ReturnValue”);
    }
    }

    /// <summary>
    /// Normalizes a yield fact value to two decimal places, and make sure that any value 0 turns into null.
    /// </summary>
    private decimal? NormalizeValue(decimal? val)
    {
    if (val == 0)
    val = null;

    if (val != null)
    val = decimal.Round(Math.Max(0, (decim

    Imported from legacy forums. Posted by nmosafi (had 1168 views)

    User (Old forums)
    Member
    Post count: 23064

    Just wondering if you have been able to reproduce this using my code sample? If so is it being looked at?

    Don’t mean to nag but the client is asking me when it will be fixed and I could do with feedback!

    Thanks
    Neil

    Imported from legacy forums. Posted by nmosafi (had 718 views)

    User (Old forums)
    Member
    Post count: 23064

    Neil,

    I have been able to reproduce and I am currently composing a reply to you, so you should see it soon!

    Imported from legacy forums. Posted by Pascal (had 812 views)

    User (Old forums)
    Member
    Post count: 23064

    Hi Neil,

    Thanks for the repro! I have been able to reproduce, and I have a fix for you!

    There are a two issues here, and we will make sure to better document all of this…

    <b><u>1. Column.DisplayMemberBinding vs Converters</u></b>

    The DisplayMemberBinding property is used to establish the binding between a Cell’s Content and a data item. The key thing to be aware of is that a cell’s content should be whatever <b>data</b> you want in that cell, not its visual (formatted) representation.

    Ususally, you’ll want to keep the data type of the cell’s content in sync with the original data field’s type. In your example, Cell.Content should contain a Decimal.

    We advise against specifying a Converter to the DisplayMemberBinding whose goal is to do <i>display</i> conversion (like converting a Decimal to a string that represents a currency). Typical uses of a Converter on the DisplayMemberBinding would be to do <i>data type</i> conversion. For example, if the original data field is a string but you want the DataGrid (via the Cell) to treat it as an integer.

    The recommended way of doing <i>visual</i> conversion is to specify a custom CellContentTemplate on the Column, and specify your Converter on the Binding(s) that are declared in that DataTemplate:

    <hr>
    <code>
    <DataTemplate x:Key=”formattedCellContentTemplate”>
    <TextBlock Text=”{Binding Converter={StaticResource FormattingConverter},
    ConverterParameter=[0:£0.00]}” />
    </DataTemplate>
    </code>
    <hr>

    <b><u>2. Binding a CellEditor to its Cell’s content</u></b>

    In your repro code, the custom CellEditors declared on the columns use an AutoSelectTextBox whose Text property is bound to the parent cell’s DataContext.Xyz value. In other words, the editor control is bound to the original data field.

    By doing this direct binding, you are effectively bypassing the DataGrid’s in-place editing infrastructure and directly altering the original data source. This is why you don’t see the changes immediately in the DataGrid: when a DataRow is being edited, we hold off any updates that come from the data source until that DataRow is no longer being edited. So here, when you type in some numbers in a Cell you are not modifying the cell’s content; you are modifying the original data source. When you move to another DataRow, the previous DataRow leaves edit mode and is updated with new content from the original data source.

    The documented way of binding an editor control is by using a CellEditorBinding, which is a markup extension that interprets and creates the binding required between a cell and its editor to allow an editor to modify the content of its associated cell.

    So, your CellEditor should be implemented like this:

    <hr>
    <code>
    <xcdg:CellEditor.EditTemplate>
    <DataTemplate>
    <xcd:AutoSelectTextBox Text=”{xcdg:CellEditorBinding}” />
    </DataTemplate>
    </xcdg:CellEditor.EditTemplate>
    </code>
    <hr>

    Unfortunately, this will break the data-type consistency I talked about in #1… When some numbers are typed into that AutoSelectTextBox and the modification is commited to the DataGrid, the Cell’s content won’t be of type Decimal anymore… It will be of type String (because this is the data type of the TextBox.Text property).

    So you should specify a converter on that CellEditorBinding to be able to convert the string back to a Decimal. Unfortunately, our CellEditorBinding markup extension doesn’t expose the Converter and ConverterParameter properties… This is a shortcoming in v1.0 of the grid that we will adress in the next release.

    So what you must do is declare a regular Binding that corresponds exactly to the Binding that the CellEditorBinding markup extension provides, and specify a Converter on that Binding:

    <hr>
    <code>
    <xcdg:CellEditor.EditTemplate>
    <DataTemplate>
    <xcd:AutoSelectTextBox Text=”{Binding RelativeSource={RelativeSource FindAncestor,
    AncestorType=xcdg:Cell},
    Path=ActualContent,
    Converter={StaticResource decimalConverter}}” />
    </DataTemplate>
    </xcdg:CellEditor.EditTemplate>
    </code>
    <hr>

    Note that this binds to the <i>ActualContent</i> property of the parent Cell. This is a property that we chose not to expose publicly in the initial release because we might refactor around it in the future and we felt that it was an implementation detail that was not worth making public and documented.

    In short, the ActualContent property reflects what must be displayed by the DataGrid for that Cell, so if that Cell has been edited but the modification was not yet commited (i.e. the DataRow is still being edited), the user sees the modified content in the Cell. When the modification is commited, ActualContent is transfered back to Content. If the modification is canceled, ActualContent is reinitialized to Content.

    You will find the fixed markup for your repro app in the following post.

    I hope my explanation was clear! If not, don’t be shy to say so and I will try to do better! 🙂

    Imported from legacy forums. Posted by Pascal (had 957 views)

    User (Old forums)
    Member
    Post count: 23064

    <Window x:Class=”WindowsApplication67.Window1″
    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml&#8221;
    xmlns:xcd=”clr-namespace:Xceed.Wpf.Controls;assembly=Xceed.Wpf.Controls”
    xmlns:xcdg=”http://schemas.xceed.com/wpf/xaml/datagrid&#8221;
    xmlns:local=”clr-namespace:WindowsApplication67″
    Title=”TestXceed”
    Height=”300″
    Width=”300″
    >
    <Window.Resources>
    <local:FormattingConverter x:Key=”FormattingConverter” />
    <local:DecimalConverter x:Key=”decimalConverter” />

    <DataTemplate x:Key=”formattedCellContentTemplate”>
    <TextBlock Text=”{Binding Converter={StaticResource FormattingConverter}, ConverterParameter=[0:£0.00]}” />
    </DataTemplate>

    <xcdg:CellEditor x:Key=”decimalCellEditor”>
    <xcdg:CellEditor.EditTemplate>
    <DataTemplate>
    <xcd:AutoSelectTextBox Text=”{Binding RelativeSource={RelativeSource FindAncestor,AncestorType=xcdg:Cell},Path=ActualContent,Converter={StaticResource decimalConverter}}” />
    </DataTemplate>
    </xcdg:CellEditor.EditTemplate>
    <xcdg:CellEditor.ActivationGestures>
    <xcdg:TextInputActivationGesture />
    </xcdg:CellEditor.ActivationGestures>
    </xcdg:CellEditor>

    </Window.Resources>

    <Grid>

    <xcdg:DataGridControl ItemsSource=”{x:Static local:Window1.YieldFacts}”
    AutoCreateColumns=”False”>
    <xcdg:DataGridControl.Columns>
    <xcdg:Column FieldName=”SingleYield”
    Title=”Single Yield”
    DisplayMemberBinding=”{Binding Path=SingleValue,Mode=TwoWay}”
    CellContentTemplate=”{StaticResource formattedCellContentTemplate}”
    CellEditor=”{StaticResource decimalCellEditor}”
    Width=”80″ />

    <xcdg:Column FieldName=”ReturnYield”
    Title=”Return Yield”
    DisplayMemberBinding=”{Binding Path=ReturnValue, Mode=TwoWay}”
    CellContentTemplate=”{StaticResource formattedCellContentTemplate}”
    CellEditor=”{StaticResource decimalCellEditor}”
    Width=”80″ />

    </xcdg:DataGridControl.Columns>

    </xcdg:DataGridControl>

    </Grid>

    </Window>

    Imported from legacy forums. Posted by Pascal (had 714 views)

    User (Old forums)
    Member
    Post count: 23064

    Pascal

    Thanks for sorting this for me! I am going to push these changes into our app and imagine it will be fine after that! I’ll let you know how I get on.

    FYI I did originally try to use CellEditorBinding but ran into DataType problems so I ended up hacking my way back to the DataContext using RelativeSource – that was obviously not the right way to go!

    Regards
    Neil

    Imported from legacy forums. Posted by nmosafi (had 1204 views)

    User (Old forums)
    Member
    Post count: 23064

    Cheers Pascal, that worked a treat!

    Neil

    Imported from legacy forums. Posted by nmosafi (had 680 views)

    User (Old forums)
    Member
    Post count: 23064

    I am glad to hear that! 😀

    Imported from legacy forums. Posted by Pascal (had 768 views)

    User (Old forums)
    Member
    Post count: 23064

    Do you still want me to look into the ResourceKeyNotFoundExceptions which were getting picked up by my Dispatcher.UnhandledException event handler?

    It’s not really a problem as I just ignore it, but I will update my test app to try and replicate it need be?

    Imported from legacy forums. Posted by nmosafi (had 915 views)

    User (Old forums)
    Member
    Post count: 23064

    Hi Guys

    Although this is now working, I have noticed another issue. When I press “Enter”, the value is not updated, but reverted back to the original value.

    Any ideas please?

    Cheers
    Neil

    Imported from legacy forums. Posted by nmosafi (had 998 views)

    User (Old forums)
    Member
    Post count: 23064

    Is your DecimalConverter being called when you hit Enter? If so, is it properly converting the string value to a Decimal?

    Imported from legacy forums. Posted by Pascal (had 877 views)

Viewing 15 posts - 16 through 30 (of 34 total)
  • You must be logged in to reply to this topic.