WPF standard ComboBox Items Source Change Issue
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的更多相关文章
- 关于WPF的ComboBox中Items太多而导致加载过慢的问题
原文:关于WPF的ComboBox中Items太多而导致加载过慢的问题 [WFP疑难]关于WPF的ComboBox中Items太多而导致加载过慢的问题 ...
- [WPF]ComboBox.Items为空时,点击不显示下拉列表
ComboBox.Items为空时,点击后会显示空下拉列表: ComboBox点击显示下拉列表,大概原理为: ComboBox存在ToggleButton控件,默认ToggleButton.IsChe ...
- DevExpress WPF入门指南:跟随 Items Source 向导完成数据绑定
Items Source Wizard Items Source Configuration Wizard允许在设计时执行数据绑定.跟随这个向导可以自动生成XAML数据绑定代码. 下面就来展示下如何使 ...
- WPF的ComboBox 数据模板自定义
WPF的ComboBox 有些时候不能满足用户需求,需要对数据内容和样式进行自定义,下面就简要介绍一下用数据模板(DataTemplate)的方式对ComboBox 内容进行定制: 原型设计如下: 步 ...
- WPF 自定义ComboBox样式,自定义多选控件
原文:WPF 自定义ComboBox样式,自定义多选控件 一.ComboBox基本样式 ComboBox有两种状态,可编辑和不可编辑状态.通过设置IsEditable属性可以切换控件状态. 先看基本样 ...
- WPF之ComboBox的VisualTreeHelper
原文:WPF之ComboBox的VisualTreeHelper 用WPF的ComboBox控件的时候,需要用到TextChanged属性,但是这个属性属于TextBox控件,不用担心,ComboBo ...
- 【WPF】ComboBox:根据绑定选取、设置固定集合中的值
问题场景 我有一个对象,里面有一个属性叫Limit,int类型.虽然int可取的范围很大,我想要在用户界面上限制Limit可取的值,暂且限制为5.10.15.20. 所以ComboBox绑定不是绑定常 ...
- WPF中ComboBox用法
The ComboBox control is in many ways like the ListBox control, but takes up a lot less space, becaus ...
- WPF 关于ComboBox在前台绑定XML数据的一些方法,使用XML数据提供器 XmlDataProvider
关于使用 数据提供器:XmlDataProvider 的一些问题,以及在WPF中是如何使用的一些介绍,还有踩到的一些坑,希望其他和我碰到一样问题的,可以更快的解决. 首先,要求是 在WPF 的前台代码 ...
随机推荐
- NotePad ++的妙用:添加代码行数和格式不变复制代码
NotePad ++ 不仅安装包小而且功能强大,可以支持很多语言.这里简单阐述下两个功能: 一.在代码前添加行数: 1.用NotePad ++打开一个文件,一般NotePad ++会自动识别这是什么语 ...
- C#学习笔记----AppDomain应用程序域
使用.Net建立的可执行程序*.exe,并没有直接承载到进程当中,而是承载到应用程序域(AppDomain)当中.应用程序域是.Net引入的一个新概念,它比进程所占用的资源要少,可以被看做是一个轻量级 ...
- hdu 1556:Color the ball(线段树,区间更新,经典题)
Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- Freemarker使用入门
一.概述: FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写 Template + data_model = output FreeMarker也是与Web容 ...
- PHPCMS 实现上一篇下一篇的几种方法
1第一种 <p>上一篇:{get sql = "select contentid,catid,url,titlee from phpcms_content where conte ...
- VMware报错:“device eth0 does not seem to be present, delaying initialization ”
转自:http://blog.sina.com.cn/s/blog_77126fa501018s3d.html vmlite虚拟机启动出错,就把这个虚拟机删除掉重新建立,系统虚拟硬盘使用之前的,启动系 ...
- How to install the zsh shell in Linux && how to set it as a default login shell
Z shell’s (zsh) popularity has increased in the last years. I have not moved too zsh yet, but I am g ...
- Linux学习笔记(10)文本编辑器vim
vim是一个功能强大的全屏幕文本编辑器,是Linux/Unix最常用的文本编辑器,其作用是建立.编辑.显示文本文件.vim的特点是没有菜单,只有命令. vim主要有三种工作模式,分别为命令模式.插入模 ...
- struts2框架快速入门小案例
struts2快速入门: index.jsp------>HelloAction--------->hello.jsp struts2流程 1.导入jar包 struts2的目录结构: a ...
- hdu 5690 All x
All X Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submiss ...