Naryoril
Naryoril

Reputation: 601

How to prevent NewItemPlaceholder row in a ComboBox bound to the same DataTable as a DataGrid in WPF

I'v a wizard style application that uses pages and the user can navigate between them either by Next and Previous buttons or by using a navigation bar to directely access certain pages.

On one page (i'll call it "grid page")i have a DataGrid bound to a DataTable. There is some initial data in the DataTable, but using the DataGrid the user can add, edit and delete rows as he wishes. On the next page (i'll call i "combo box page") have a ComboBox which is bound to the same DataTable as the DataGrid on the grid page. Both pages use the same object as data context.

If i jump to the combo box page directly everything works fine, the combo box has an entry for each row in the DataTable like it's supposed to be. Now i navigate to the grid page and don't touch anything there and then go to the combo box page again. Now the ComboBox displays a new item, a NewItemPlaceholder. Obviously this happens because the DataGrid has UserCanAddRows set to true and thus displays a placeholder row for a new item. But this should only concern the DataGrid and not the bound DataTable, so in my eyes this is a bug, or at least an absolutely horrible design.

Of course i don't want the NewItemPlaceholder in my ComboBox (and selecting it causes a lot of problems). So how can i prevent it from being displayed in the ComboBox?

Update: In the meantime i found out the placeholder item isn't in the DataTable as a row, which makes it even stranger, unless there is a flag in a DataTable that says "there is a NewItemPlaceholder in this table" but isn't a row itself. Additionally when i register to the Initialized event of the ComboBox i have the 2 items i'm looking for, when i register to the Loaded event i have the NewItemPlaceholder as well, so it must be added somewhere between those 2 events.

Upvotes: 5

Views: 2400

Answers (3)

Monika Prabha
Monika Prabha

Reputation: 1

Use a CollectionViewSource to bind one control(Combobox) and collection property defined in ViewModel to bind another control (Datagrid).

Property in ViewModel :

private List<Rate> _rate = new List<Rate>();
   public List<Rate> RatePlans
     {
       get { return _rate; }
       set
       {
         _rate = value;
          OnPropertyChanged("RatePlans");
       }
     }

Then in XAML :

<UserControl >
      <UserControl.Resources >
            <CollectionViewSource Source="{Binding RatePlans}" x:Key="RatesSource" />
        </UserControl.Resources>
      <Grid Name="LayoutGrid">
      <Grid.RowDefinitions>
         <RowDefinition/>
         <RowDefinition/>
      </Grid.RowDefinitions>
      <ComboBox Grid.Row="0" DisplayMemberPath="RatePlanName"  ItemsSource="{Binding Source={StaticResource RatesSource}}" HorizontalAlignment="Stretch"/>
    <DataGrid Grid.Row="1" HorizontalAlignment="Stretch" CanUserAddRows="True" AutoGenerateColumns="False"  ItemsSource="{Binding RatePlans}">
     <DataGrid.Columns>
      <DataGridTextColumn Binding="{Binding RatePlanName}" Header="Rate Plan" />
      <DataGridTextColumn Binding="{Binding RoomType}" Header="Room Type" />
      <DataGridTextColumn Binding="{Binding Price}" Header="Price"/>
      </DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>

Upvotes: 0

Karl Wiedemann
Karl Wiedemann

Reputation: 63

Use a CollectionViewSource. The problem occurs when more than one control shares the same view of a collection such as when a collection is bound in one case to a DataGrid and in another to the ComboBox. If the DataGrid allows the user to add items (i.e., the DataGrid's CanUserAddRows is true), the NewItemPlaceholder may have been added to the view. Try something like

<UserControl >
<UserControl.Resources >
    <CollectionViewSource Source="{Binding MyCollection}"
             x:Key="SourceWithoutNewItemPlaceholder" />
</UserControl.Resources>

  <Grid Name="LayoutGrid" >

   <ComboBox ItemsSource={Binding Source={StaticResource SourceWithoutNewItemPlaceholder}} >

  </Grid>
</UserControl>

Upvotes: 6

Naryoril
Naryoril

Reputation: 601

After several failed attempts i found 2 solutions:

1) In the Loaded event of the page i make a binding in the code behind, not to the DataTable itself, but to a DataTable.ToList. If i do it that way the NewItemPlaceholder won't show up.

2) In the view model i make a new property which returns the DataTable.ToList and bind to it. This way i can do the binding in XAML.

Just for reference, methods that don't work: Filter property on the ComboBox throws a NotSupportedException, seems the DataTable doesn't support this. Deleting the NewItemPlaceholder in the Loaded event of the ComboBox doesn't work either because you can't delete items when an ItemsSource is set. Removing the NewPlaceHolderItem when leaving the page with the data grid doesn't work either, because i can't find where it is (it's not in the DataTable or the View of the DataTable)

Upvotes: 0

Related Questions