简体   繁体   中英

ComboBox with “Refresh” Entry

I've the following situation in my project and i'm wondering what's the best way to achieve my goal.

Goal: Having a combobox with itemsource binding and one entry which is functioning like a refresh button (fetching items from database and update combobox items).

Currently I set up my combobox with itemsource binding (see below), but currently i'm struggling with the binding of the command for refreshing.

ItemsSource Binding:

<UserControl.Resources>
<CollectionViewSource x:Key="ProjectSource" Source="{Binding Projects, ElementName=Ancestor}"/>
    <CompositeCollection x:Key="ProjectCollection">
        <CollectionContainer Collection="{Binding Source={StaticResource ProjectSource}}"/>
        <Button Content="Refresh!"/>
    </CompositeCollection>

</UserControl.Resources>

Where Projects is a dependency property with an enumeration of items, another dependency property with the refresh command (an ICommand) is also available.

My ComboBox ist defined as follows:

<ComboBox SelectedValue="{Binding Project}"
                  ItemsSource="{StaticResource ProjectCollection}"
                  VerticalContentAlignment="Center"
                  HorizontalAlignment="Left"
                  Name="Box"
                  IsHitTestVisible="{Binding IsEditable}"
                  IsEnabled="{Binding IsEnabled, Mode=OneWay, IsAsync=True}">

            <ComboBox.Resources>
                <DataTemplate DataType="{x:Type viewModels:ProjectViewModel}">
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>>
            </ComboBox.Resources>

        </ComboBox>

The problem is that the Command can't find the source of the binding, so the question is am i on the right way doing it and there is a solution, or am I on the wrong way (which would be better?).

Sure i could just add a button next to my combobox, but i'd like to have it in my combobox. :)

Btw.: I'm trying to follow the MVVM pattern.

I have solved this issue in the past by using code behind. When the combobox loads, create a new List<objects> of the Projects and add a Refresh string (maybe "<Refresh...>" ) to the list, and finally setting the ItemsSource to this list. Use a template selector to show the appropriate DataTemplate. When the selection changes, check if the Refresh string was selected, and if so, do your refresh, and reload the combobox. When you refresh, you can try to set the selection back to the previously selected item, or index 0, so the user can never have "refresh" selected in the combobox.

Some snippets to demonstrate.

in ctor

SelectedProjectComboBoxTemplateSelector.StringTemplate = FindResource("StringTemplate") as DataTemplate;
SelectedProjectComboBoxTemplateSelector.ProjectTemplate = FindResource("ProjectTemplate") as DataTemplate;
SelectedProjectComboBox.SelectionChanged += SelectedProjectComboBox_SelectionChanged;
SelectedProjectComboBox.ItemTemplateSelector = new SelectedProjectComboBoxTemplateSelector();

and

void SelectedProjectComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
    if (SelectedProjectComboBox.SelectedItem is string && ((string)SelectedProjectComboBox.SelectedItem) == RefreshProjectSelectionItem) {
        object current = e.RemovedItems.Count > 0 ? e.RemovedItems[0] : null;

        bool ret = RefreshData(); // from db
        if (ret) {
            LoadData(); // repopulate combobox
        } else {
            SelectedProjectComboBox.SelectedItem = current;
        }               
    }
}

and

public class SelectedProjectComboBoxTemplateSelector : DataTemplateSelector {
    public static DataTemplate StringTemplate { get; set; }
    public static DataTemplate ProjectTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container) {
        if (item == null || Designer.IsInDesignMode) return null;

        if (item is string) return StringTemplate;
        if (item is Project) return ProjectTemplate;

        return null;
    }
}

You get the idea... This should be enough to get you going if this solution meets your needs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM