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. java 中的一个项目如何做到访问另一个项目的一个方法 或者 页面

    两种方法:1.将一个项目打成jar包,第二个项目进行导入该jar包,就可以使用第一个项目里的类方法属性等2.将第一个项目发布出去,然后第二个项目调用,所谓发布出去就是开发远程接口,允许其他人调用.

  2. javascript - 事件详解

    一.事件流 1.事件流 描述的是在页面中接受事件的顺序 2.事件冒泡 由最具体的元素接收,然后逐级向上传播至最不具体的元素的节点 (最具体 –> 最不具体) 3.事件捕获 最不具体的节点先接收事 ...

  3. Go 中的反射要点

    简介 反射是元数据编程的一种形式,指的是程序获得本身结构的一种能力.不同语言的反射模型实现不一样,本文中的反射,仅仅指的是Go语言中的反射模型. 类型以及接口 这个基本概念需要清晰,这里不详细展开. ...

  4. Git提交基本流程

    在无其他分支,大家都向同一分支master分支提交代码的情况下: 1.查看本地对代码的修改情况,即可以被提交的修改记录 git status 其中被修改过的文件标识为modified,删除的文件del ...

  5. [UI]实用案例--Shape绘制实用圆圈

    Android允许通过xml定义资源,常见的事string,id,integer,dimen等,也可以定义一些图片资源,比如用来做几何的矢量图就非常好用,其中有许多的细节问题,具体需求可以再结合goo ...

  6. 总结列表显示ListView知识点

    全选ListView的item条目 单选ListView的条目 多选ListView的item条目 自定义ArrayAdapter动态改变ListView的不同item样式 动态增加和删除ListVi ...

  7. Codeforces Round #369 (Div. 2) C. Coloring Trees DP

    C. Coloring Trees   ZS the Coder and Chris the Baboon has arrived at Udayland! They walked in the pa ...

  8. Arduino101学习笔记(五)—— 模拟IO

    1.配置IO管脚 //***************************************************************************************** ...

  9. 【maven】 pom.xml内容没有错,但一直报错红叉 解决办法

    1.首先看一下下面的这两个项目,一个是新建的,一个是原来的老项目 2.myEcplise中是点击如下图 Maven4MyEcplise, Ecplise中也是右键,只不过点击Mavene而已,两个一样 ...

  10. HDU 5652 India and China Origins(经典并查集)

    特别经典的一个题,还有一种方法就是二分+bfs 题意:空间内n*m个点,每个点是0或者1,0代表此点可以走,1代表不能走.接着经过q年,每年一个坐标表示此点不能走.问哪年开始图上不能出现最上边不能到达 ...