Issue between Datagrid and ItemsControl

Mar 24, 2009 at 6:57 PM
Edited Mar 25, 2009 at 9:59 AM
Hi,

I currently have an ObservableCollection<T> that is binded to both a WPF Toolkit Datagrid and an ItemsControl.

In order for the user to be abble to insert new values into the datagrid I add (in code-behind) the first item to the Collection. However, by doing so, The itemsControl gets not one but two items??!!???....

Even If I delete the datagrid first row.. it will always stay one item of the ItemsControl (One is allways there - the ItemTemplate, it seems)??!!....

Can you understand what It went wrong?? Or a way to fix this?

NOTE: If I don't add in code behind the item, the itemsControl works correctly (but the user doe not have the option of inserting new data (rows) in the datagrid.

Thanks in advance
Coordinator
Mar 24, 2009 at 8:39 PM
You should not need to add items manually. If T is a type with a default constructor (a constructor with no arguments), then the ListCollectionView that is automatically created for the ObservableCollection<T> should be able to create the new item.

The ListCollectionView will also have a new item placeholder to represent the new row before it's actually added. The placeholder is just an object, so it will not be of type T. Perhaps this is what you are seeing in the ItemsControl.

Ben
Mar 25, 2009 at 10:13 AM
Thanks for you input Ben,

I'm currently using the following XAML code:

<toolkit:DataGrid x:Name="dg" CanUserAddRows="True" CanUserDeleteRows="True" ItemsSource="{Binding}" AutoGenerateColumns="False">
...
<toolkit:DataGrid>

And, on the code-behind:

ObservableCollection<sObject> LetsTry = new ObservableCollection<sObject>

LetsTry.Add(new  sObject());
dg.DataContext = LetsTry;

By using this, I start with two rows (so far, the only way I've managed to be able to add rows on the datagrid in run mode).. You say it's possible to have he same functionality (being able to add rows) without adding in code behind a new sObject?

If so, please can you tell me how? (It's been a big headache for me -- I'm a rookie so many things are headaches .. :P)

Thanks in advance
Coordinator
Mar 25, 2009 at 7:29 PM
Since CanUserAddRows is true, you are seeing the item that you added and the new item placeholder row. The new item placeholder row allows users to type into that row to create new items. If you add no items (remote the line LetsTry.Add(new sObject()), you should see only the new item placeholder row.

Ben
Mar 26, 2009 at 12:06 PM

Thanks Ben,

I have already resolved the issue of having only the item placeholder row.. However the ItemsControl still displays the item regarding the placeholder row...

I think it is kind of a wierd behaviour... although I do understand the need to have a placeholder row, the corresponding item should be "invisible" (temporary..whatever) or not available to other WPF objects (like .. in this case the ItemsControl)...

Is there a workaround for this? like setting the ItemsControl "extra" item visibility to hidden?

Thanks in advance
Coordinator
Mar 31, 2009 at 10:23 PM
Could you show how you bind the ItemsControl (not the DataGrid)? I would have thought that two different CollectionViews would have been used, but perhaps that is not happening. You could try creating two different ListCollectionView instances for the same ObservableCollection and assigning those to ItemsSource of DataGrid and ItemsControl (it's important that they be two different instances of ListCollectionView).

Ben
Apr 1, 2009 at 5:14 PM
Edited Apr 1, 2009 at 10:26 PM
This is the code I'm using:

<Canvas>

<ItemsControl x:Name="itmcSymbols" ItemsSource="{Binding}">

    <ItemsControl.ItemsPanel>

        <ItemsPanelTemplate>

            <Canvas/>

        </ItemsPanelTemplate>

    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>

        <DataTemplate>

                <Ellipse Height="7" Width="7" Opacity="0.75"

                    Fill="LimeGreen" Stroke="Black"

                    />

        </DataTemplate>

    </ItemsControl.ItemTemplate>

    <ItemsControl.ItemContainerStyle>

        <Style>

            <Setter

                Property="Canvas.Left"

                Value="{Binding Path=XCoordinate}" />

            <Setter

                Property="Canvas.Bottom"

                Value="{Binding Path=YCoordinate}" />

        </Style>

    </ItemsControl.ItemContainerStyle>

</ItemsControl>

</Canvas> 


And in code-behind I do the binding to the ObservableCollection<T>

If you try it you will see an "extra" item.. due to the new item placeholder...

Is this expected? or it's a bug? from my point of view it should not display the "extra" item....
Is there a work around?

Thanks in advance

Coordinator
Apr 3, 2009 at 1:55 AM
When I tried this, I was able to see the extra item in the ItemsControl. When I changed the DataContext of the two controls to be two different instances of ListCollectionView, the ItemsControl did not have the extra item.

dataGrid.DataContext = new ListCollectionView(myCollection);
itemsControl.DataContext = new ListCollectionView(myCollection);

Ben
Apr 3, 2009 at 10:14 AM
Yup..

It worked exactly like you sayed... Many thanks Ben....

Problem solved!!!