Today I encountered an issue with the WPF standard CombBox where if the bound ItemsSource (collection) of a ComboBox has changed the binding on the SelectedItem of the ComboBox will fail to update to the already properly set view model property.

For example if the ItemsSource is bound to the following property of the view model which is common and presumably the best practice:

 public ObservableCollection<string> Items { get; private set; }

And the SelectedItem is bound to

 public string SelectedItem
{
get { return SelectedModel.SelectedItem; }
set
{
SelectedModel.SelectedItem = value;
OnPropertyChanged();
}
}

And the SelectedModel can be changed this way:

 public Model SelectedModel
{
get { return _selectedModel; }
set
{
if (_selectedModel != value)
{
_selectedModel = value; Items.Clear();
foreach (var item in _selectedModel.Items)
{
Items.Add(item);
} OnPropertyChanged("SelectedItem");
}
}
}

where each SelectedItem on SelectedModel has already been properly set up.

One might suppose it would work. However it doesn't.

The reason is kind of explained in this article,

http://stackoverflow.com/questions/5242275/combobox-itemssource-changed-selecteditem-is-ruined

As I've done a few experiments, I have feeling that the (initial) binding update is lost due to the fact that the framework modifies the SelectedItem property and holds certain assumptions as to the modification during the collection (Items) change and neglects property changed notification afterwards if things went against its assumption (no matter when it happens, and only not when the property actually changes from its value as of the end of the collection process).

Given the above speculation, I continued playing with the code and eventually come up with a workable solution like below (complete source code).

View model:

 using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using ComboBoxItemsSourceChangeTest.Annotations; namespace ComboBoxItemsSourceChangeTest
{
/// <summary>
/// The view model of the main UI
/// </summary>
/// <remarks>
/// http://stackoverflow.com/questions/5242275/combobox-itemssource-changed-selecteditem-is-ruined
/// </remarks>
public class MainViewModel : INotifyPropertyChanged
{
private Model _selectedModel; private bool _isComboTransitioning; public MainViewModel()
{
Items = new ObservableCollection<string>();
} public Model SelectedModel
{
get { return _selectedModel; }
set
{
if (_selectedModel != value)
{
_selectedModel = value; _isComboTransitioning = true;
Items.Clear();
foreach (var item in _selectedModel.Items)
{
Items.Add(item);
}
_isComboTransitioning = false; OnPropertyChanged("SelectedItem");
}
}
} public ObservableCollection<string> Items { get; private set; } public string SelectedItem
{
get
{
return _isComboTransitioning ? null: SelectedModel.SelectedItem;
}
set
{
if (SelectedModel.SelectedItem != value && !_isComboTransitioning)
{
SelectedModel.SelectedItem = value;
OnPropertyChanged();
}
}
} public event PropertyChangedEventHandler PropertyChanged; [NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
} public void RaisePropertyChanged(string propertyName)
{
OnPropertyChanged(propertyName);
}
}
}

Model:

 namespace ComboBoxItemsSourceChangeTest
{
public class Model
{
public string[] Items { get; set; } public string SelectedItem { get; set; }
}
}

View:

 <Window x:Class="ComboBoxItemsSourceChangeTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<ComboBox Margin="10" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}"
Name="ComboBox1">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button Margin="10" Name="Button1" Click="Button1_Click">Data Source 1</Button>
<Button Margin="10" Name="Button2" Click="Button2_OnClick">Data Source 2</Button>
<Button Margin="10" Name="Button3" Click="Button3_OnClick">Data Source 3</Button>
<Button Margin="10" Name="ButtonRandomSelect" Click="ButtonRandomSelect_OnClick">Random Select</Button>
</StackPanel>
</Grid>
</Window>

WPF standard ComboBox Items Source Change Issue的更多相关文章

  1. 关于WPF的ComboBox中Items太多而导致加载过慢的问题

    原文:关于WPF的ComboBox中Items太多而导致加载过慢的问题 [WFP疑难]关于WPF的ComboBox中Items太多而导致加载过慢的问题                          ...

  2. [WPF]ComboBox.Items为空时,点击不显示下拉列表

    ComboBox.Items为空时,点击后会显示空下拉列表: ComboBox点击显示下拉列表,大概原理为: ComboBox存在ToggleButton控件,默认ToggleButton.IsChe ...

  3. DevExpress WPF入门指南:跟随 Items Source 向导完成数据绑定

    Items Source Wizard Items Source Configuration Wizard允许在设计时执行数据绑定.跟随这个向导可以自动生成XAML数据绑定代码. 下面就来展示下如何使 ...

  4. WPF的ComboBox 数据模板自定义

    WPF的ComboBox 有些时候不能满足用户需求,需要对数据内容和样式进行自定义,下面就简要介绍一下用数据模板(DataTemplate)的方式对ComboBox 内容进行定制: 原型设计如下: 步 ...

  5. WPF 自定义ComboBox样式,自定义多选控件

    原文:WPF 自定义ComboBox样式,自定义多选控件 一.ComboBox基本样式 ComboBox有两种状态,可编辑和不可编辑状态.通过设置IsEditable属性可以切换控件状态. 先看基本样 ...

  6. WPF之ComboBox的VisualTreeHelper

    原文:WPF之ComboBox的VisualTreeHelper 用WPF的ComboBox控件的时候,需要用到TextChanged属性,但是这个属性属于TextBox控件,不用担心,ComboBo ...

  7. 【WPF】ComboBox:根据绑定选取、设置固定集合中的值

    问题场景 我有一个对象,里面有一个属性叫Limit,int类型.虽然int可取的范围很大,我想要在用户界面上限制Limit可取的值,暂且限制为5.10.15.20. 所以ComboBox绑定不是绑定常 ...

  8. WPF中ComboBox用法

    The ComboBox control is in many ways like the ListBox control, but takes up a lot less space, becaus ...

  9. WPF 关于ComboBox在前台绑定XML数据的一些方法,使用XML数据提供器 XmlDataProvider

    关于使用 数据提供器:XmlDataProvider 的一些问题,以及在WPF中是如何使用的一些介绍,还有踩到的一些坑,希望其他和我碰到一样问题的,可以更快的解决. 首先,要求是 在WPF 的前台代码 ...

随机推荐

  1. 网络中文乱码问题 utf-8

    // 网络中文乱码问题 utf-8 [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

  2. Dubbo应用与异常记录

    结合项目里使用暴露出的问题,对并发较多的核心业务或者对请求失败等敏感的业务场景不太建议使用Dubbo, 如电商的购买等行为,使用Dubbo就必须阅读源码,熟悉相关机制,或者直接自己造轮子. >& ...

  3. Linux Shell 高级编程技巧3----运行级别脚本介绍

    3.运行级别脚本介绍    3.1.运行级别        运行级别介绍:            0    关机            1    单用户模式            2    多用户模式 ...

  4. golang基础知识之encoding/json package

    golang基础知识之json 简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式.可以去json.org 查看json标准的清晰定义.json pack ...

  5. hdu 4731 2013成都赛区网络赛 找规律

    题意:找字串中最长回文串的最小值的串 m=2的时候暴力打表找规律,打表可以用二进制枚举

  6. poj 3468【线段树】

    题意:给定Q(1<=Q<=100000)个数A1,A2…AQ,以及可能多次进行的两个操作 1)对某个区间Ai……Aj的每个数都加n(n可变) 2)对某个区间Ai……Aj的数求和 分析: 树 ...

  7. 退出Activity(转)

    退出Activity 如何退出Activity?如何安全退出已调用多个Activity的Application? 退出activity 直接调用 finish () 方法 . //用户点击back键  ...

  8. Database.com SOQL and SOSL Reference

    如下是关于 SOQ L与 SOSL 的相关链接: http://docs.database.com/dbcom/en-us/db_sosl_soql/sforce_api_calls_soql.htm ...

  9. MySQL级联删除的问题

    一.FOREIGN KEY 的定义分为两种:列级约束和表级约束 .列及约束的话,可以在列定义的同时,定义外键约束.比如 如果有2张表,主表:T1(A1 )) 要在从表T2中定义外键列这可以: Crea ...

  10. 用js实现图片自动加载的瀑布流效果

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...