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 的前台代码 ...
随机推荐
- Delphi集合的用法
参考:http://www.cnblogs.com/doit8791/archive/2012/08/17/2644859.html 集合是Pascal特有的数据类型,在Visual Basic.C/ ...
- C编译: 动态连接库 (.so文件)(转摘)
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在“纸上谈兵: 算法与数据结构”中,我在每一篇都会有一个C程序,用于实现算法和数据 ...
- JqueryEasyUI 解决IE下datagrid无法刷新的问题 分类: JavaScript JqueryEasyUI 2014-09-20 10:05 510人阅读 评论(1) 收藏
问题描述: 在使用JqueryEasyUI 时,发现在IE下$('#table').datagrid('reload');无效,数据并没有被刷新,究其原因,是因为刷新时,datagrid请求的url没 ...
- android 入门-Service
sdk 1.7 package com.example.hellowrold; import java.util.Random; import com.example.hellowrold.R.id; ...
- [Linux] 取得服务器版本
1) 登录到服务器执行 lsb_release -a ,即可列出所有版本信息,例如: [root@3.5.5Biz-46 ~]# lsb_release -a LSB Version: 1.3 Dis ...
- Ubuntu下配置samba实现文件夹共享
转自:http://www.cnblogs.com/phinecos/archive/2009/06/06/1497717.html 一. samba的安装: sudo apt-get insall ...
- tree view
<TreeView x:Name="treeParameter" Width=" Margin="11,6,11,6" ItemsSource= ...
- 通信原理实践(一)——音频信号处理
一.信号的离散化 1.采样定理: –如果信号是带限的,并且采样频率fs超过信号最高频率的两倍,那么,原来的连续信号可以从采样样本中完全重建出来. 因此在仿真过程中,采样率(fs)是一个非常重要的参数. ...
- android如何实现文件按时间先后顺序排列显示
<span style="font-size:18px;">File[] files =parentFile.listFiles(fileFilter);//通过fil ...
- HTML5实践 -- 使用CSS3 Media Queries实现响应式设计
CSS3 Media用法介绍:http://www.w3cplus.com/content/css3-media-queries 转载请注明原创地址:http://www.cnblogs.com/so ...