【问题标题】:ComboBox with "Refresh" Entry带有“刷新”条目的组合框
【发布时间】:2016-01-20 03:29:03
【问题描述】:

我的项目中有以下情况,我想知道实现目标的最佳方法是什么。

目标:拥有一个带有 itemsource 绑定的组合框和一个功能类似于刷新按钮的条目(从数据库中获取项目并更新组合框项目)。

目前我使用 itemsource 绑定设置我的组合框(见下文),但目前我正在为刷新命令的绑定而苦苦挣扎。

ItemsSource 绑定:

<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>

其中 Projects 是具有项枚举的依赖属性,另一个具有刷新命令(ICommand)的依赖属性也是可用的。

我的 ComboBox 定义如下:

<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>

问题是命令找不到绑定的来源,所以问题是我是在正确的方式上做它并且有解决方案,还是我在错误的方式上(哪个更好? )。

当然我可以在我的组合框旁边添加一个按钮,但我想把它放在我的组合框中。 :)

顺便说一句:我正在尝试遵循 MVVM 模式。

【问题讨论】:

  • 请记住,上面的示例中没有命令绑定,因为它不起作用。 :)
  • 我对可用性很好奇。这是否意味着刷新项始终位于索引 0 中?如果没有,如果您有大量项目,您的用户将需要在组合列表中找到它。
  • @tgpdyk 关于我的可用性,这很好,因为只有当某个项目不在列表中时才需要刷新,这种情况大约每年 5 次。

标签: c# wpf mvvm combobox


【解决方案1】:

我过去通过使用后面的代码解决了这个问题。当组合框加载时,创建Projects 的新List&lt;objects&gt; 并将Refresh string(可能是"&lt;Refresh...&gt;")添加到列表中,最后将ItemsSource 设置为此列表。使用模板选择器显示适当的 DataTemplate。选择更改后,选中Refresh string Refresh string,如果是,请执行刷新,然后重新加载ComboBox。刷新时,您可以尝试将选择设置回之前选择的项目,或索引 0,因此用户永远无法在组合框中选择“刷新”。

一些 sn-ps 来演示。

在演员中

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

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;
        }               
    }
}

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;
    }
}

您明白了...如果此解决方案满足您的需求,这应该足以让您继续前进。

【讨论】:

  • @Thoor,只是好奇您是否找到了解决问题的方法?以上有帮助吗,还是您使用了其他方法?
  • 我将其标记为答案,因为它与我的解决方案非常相似。我最终将 ItemsSource 绑定到我的 ProjectViewModel 列表。当 get on my list 被调用时,我返回项目列表和一个从 ProjectViewModel 继承的 RefreshViewModel。如果现在 SelectedValue 绑定已更新,我将检查给定的类型并设置项目或刷新列表。 RefreshViewModels Equals 方法被覆盖并返回 false,因此无法选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-29
  • 1970-01-01
  • 2010-11-14
  • 1970-01-01
  • 2011-01-04
  • 1970-01-01
相关资源
最近更新 更多