开发者

How do I bind combobox text to legacy data not in the drop down list?

The drop-down list (itemssource) of my combobox contains new product request items. I want to bind to legacy data that is not in the drop-down list. To complicate things I'm using multibinding with an IMultiValueConverter to combine fields for display. Also, the names of bound fields do not match the names of the properties I'm bound to.

The combobox itemssource is a list of NewProductRequests. From this NPR object NewProdNumber and NewProdName are combined for display in the drop-down list by my type converter. The ConvertBack method returns the values NewProdNumber and NewProdNumberCombinedWithName. These two values will be saved to database fields with slightly different names. For this example I'll call them DBProdRequestNumber and DBProdRequestTitle.

I've succeeded in displaying and saving new items. The problem is I haven't figured out how to display legacy data that is not in the list. It's not in the list because it no longer qualifies as a new product request.

Here is the problem XAML (the itemssource is set in code-behind):

<ComboBox x:Name="NPRComboBox" IsSynchronizedWithCurrentItem="False" IsEditable="False">
    <ComboBox.SelectedItem>
        <MultiBinding Converter="{StaticResource combineNPRStuffMultiConverter}">
            <Binding Path="DBProdRequestNumber" UpdateSourceTrigger="PropertyChanged"/>
            <Binding Path="DBProdRequestTitle" UpdateSourceTrigger="PropertyChanged"/>
        </MultiBinding>
    </ComboBox.SelectedItem>
    <ComboB开发者_运维知识库ox.ItemTemplate>
        <DataTemplate>
            <TextBlock DataContext="{Binding}">
                <TextBlock.Text>
                    <MultiBinding  Converter="{StaticResource combineNPRStuffMultiConverter}">                             
                        <Binding Path="NewProdNumber" UpdateSourceTrigger="PropertyChanged"/>                              
                        <Binding Path="NewProdNumberCombinedWithName" UpdateSourceTrigger="PropertyChanged"/>
                    </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

A similar problem with a datagrid and combobox I solved using a DataGridTemplateColumn.CellEditingTemplate based on this MSDN Magazine example from Julie Lerman. Of course, in this case I'm not using a datagrid.

Thanks in advance for any help.


This answer (to my own question) was pulled from a comment in the NathanAW answer:

Unfortunately I can't include legacy items in the ItemsSource. The list is from a web service that is out of my control. I devised a kludgy solution which I don't really like (but it works)...Since I know the combobox is needed only for new records it is visible only when the user clicks "Add". In the same location I placed a textbox bound to the legacy data that is visible when NOT in add mode. So, I toggle the visiblity of each control as the app switches in and out of add mode. I'm sure there is a better way!


It seems that you might be able to simplify this by not using a Multi-Binding converter. If you have a collection of NPR objects, then you can set that as the ItemsSource for the listbox. Then use the DataTemplate to format how you want that item displayed.

With this setup, you can construct a template that shows multiple fields from the NPR object in a single TextBlock using something like:

<ComboBox 
    x:Name="NPRComboBox" 
    IsSynchronizedWithCurrentItem="False" 
    IsEditable="False" 
    SelectedItem={Binding SelectedNPR, Mode=TwoWay}" 
>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock>
               <Run Text="{Binding Path=NewProdNumber, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" />
               <Run> - </Run>
               <Run Text="{Binding Path=NewProdNumberCombinedWithName, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" />
            </TextBlock>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

If you have additional properties on the NPR object that you'd like to access, you can add an additional section to the template.

Notice that the "selected" item is bound two-way back to a property on your ViewModel (or code-behind, or whatever). This would be something like:

public NPR SelectedNPR
{
   get { ... }
   set 
   {
       ...
       // don't forget INotifyPropertyChanged
       ...
   }
}

EDIT

Here is a sample that seems to do what you've indicted about showing legacy data in the "SelectionBox", but not in the drop down list. To test this, try running it in KaXaml or something. Then start typing "Hello 3" and see that it suggests "Hello 30". This indicates that the Combo knows about the item. Now drop the list down and see that it isn't in the list. If you arrow down with the arrow keys, it skips from "Hello 20" to "Hello 40".

The next step would be to setup your templates so that the ListBoxItem template's Visibility is bound to "IsLegacy" on your NPR object. Then add both legacy and new items to the ItemsSource collection and bind to the list.

<ComboBox IsEditable="True">
  <ComboBoxItem >Hello 10</ComboBoxItem>
  <ComboBoxItem >Hello 20</ComboBoxItem>
  <ComboBoxItem Visibility="Collapsed">Hello 30</ComboBoxItem>
  <ComboBoxItem >Hello 40</ComboBoxItem>
</ComboBox>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜