问题场景:
界面上有个ListBox控件,它的内容Item绑定了一个列表,即 ItemsSource =”{Binding StudentList}”。这个StudentList列表在该界面View对应的ViewModel中赋值。ListBox中每个元素Item都是一个Student实体类对象,核心代码如下:

View:

<ListBox
x:Name="studentLB" Margin="0"
VerticalAlignment="Top"
HorizontalAlignment="Left"
HorizontalContentAlignment="Stretch"
ScrollViewer.CanContentScroll="False"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ItemsSource="{Binding StudentList}"> <!-- 流式布局,左对齐 -->
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Left"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel> <!-- 条目的模板 -->
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Bingding FirstName}" />
</DataTemplate>
</ListBox.ItemTemplate> </ListBox>

ViewModel:

private ObservableCollection<Student> studentList;
public ObservableCollection<Student> StudentList // 前台ListBox的ItemsSource绑定该列表
{
get { return studentList; }
set { SetProperty(ref studentList, value); }
}

Student.cs实体类

public Class Student
{
public int Id { get; set; } // 唯一标识符
public string FirstName { get; set; }
public string LastName { get; set; }
}

需求:现在条目中TextBlock 绑定的是Student对象的FirstName属性,如何将其改为绑定到LastName属性?

思路:

  • 思路一:
    由于ItemsSource绑定到ViewModel中的StudentList列表,在Controller层从服务端获取到列表数据后,先进行加工,再赋值给StudentList。如先用一个临时列表TempList记录服务端返回的数据,然后遍历并修改该列表中的内容,想修改后的内容赋值给StudentList,如下:

// 由于前台TextBlock绑定的是FirstName属性,现将FirstName的值改为LastName的值,即保持前台绑定不变的情况下,动态修改被绑定的属性的值。
foreach(Student item in TempList)
{
//sourceList是从服务端获取的列表数据
foreach(Student source in SourceList)
{
if (item.id == source.id)
{
item.FirstName = source.LastName;
}
}
}

经过测试,虽然数据层的确发生了改变,但显示层却并没有更新。说好的MVVM呢?怎么会数据变了不自动更新界面的??

  • 思路二:
    将ListBox的界面改为采用Style样式,准备两种样式,区别仅在于TextBlock绑定到的是FirstName还是LastName。在Controller层动态修改ListBox使用的样式!如可以用一个按钮,每次点击都来回切换这两种样式。

新建样式文件StudentStyle.xaml:

<!-- ListBox样式 切换显示学生的FirstName/LastName -->
<!-- 这两种样式仅有ListBoxItem中的TextBlock绑定到FirstName/LastName的不同 --> <ResourceDictionary x:Class="YourProjectName.Presentation.Style.ListBox_StudentStyle"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"> <!-- 样式1:显示FirstName -->
<Style x:Key="firstNameStyle" TargetType="{x:Type ListBox}">
<Setter Property="Margin" Value="0"/>
<Setter Property="ItemsSource" Value="{Binding SpacePlansList}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Visible"/> <!-- 流式布局 左对齐 -->
<Setter Property="ListBox.ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Left"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter> <Setter Property="ListBox.ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding FirstName}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style> <!-- 样式2:显示LastName -->
<Style x:Key="lastNameStyle" TargetType="{x:Type ListBox}">
<Setter Property="Margin" Value="0"/>
<Setter Property="ItemsSource" Value="{Binding SpacePlansList}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Visible"/> <!-- 流式布局 左对齐 -->
<Setter Property="ListBox.ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Left"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter> <Setter Property="ListBox.ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding LastName}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style> </ResourceDictionary>

View:

<!-- 引入样式资源 -->
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Presentation/Style/ListBox_StudentStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources> <!-- 使用样式,默认使用显示FirstName的样式 -->
<ListBox x:Name="studentLB" Style="{StaticResource firstNameStyle}"/>

控制层动态修改ListBox的样式:

private Style listbox_FirstNameSytle;   // 显示FirstName的样式
private Style listbox_LastNameSytle; // 显示LastName的样式 // 在控制层的初始化方法中,获取这两种样式
public void Initialize()
{
var listBoxStyle = new ResourceDictionary
{
Source = new Uri("/YourProjectName;component/Presentation/Style/ListBox_StudentStyle.xaml", UriKind.RelativeOrAbsolute) // 指定样式文件的路径
}; listbox_FirstNameSytle = listBoxStyle["firstNameStyle"] as Style;
listbox_LastNameSytle = listBoxStyle["lastNameStyle"] as Style;
} private void btn_Click(object sender, RoutedEventArgs e)
{
// 根据按钮的状态,切换ListBox的样式
if (view.btn.IsChecked == true)
{
view.studentLB.Sytle = listbox_LastNameSytle;
}
else
{
view.studentLB.Sytle = listbox_FirstNameSytle;
}
}

经测试,该方法可行!


小结:

准备多套样式,通过动态修改样式来实现类似于动态修改绑定的效果。

【WPF】MVVM动态修改Bingding的另一种思路——用Style样式的更多相关文章

  1. (WPF) MVVM: 动态添加控件及绑定。

    比如需要显示一个键盘,里面有各个按键.实现的效果如下: 之前的思路,就是建立一个singleKey的控件,然后在后台用代码动态的添加到父控件里去, 再用代码在后台进行绑定. 这种实现方法并不是真正的M ...

  2. 关于Unity中如何代码动态修改天空盒

    在Unity中动态修改天空盒有两种方法: 一.为每个Texture建立天空盒材质球,需要更换时直接将对应材质球作为天空盒,缺点是建立的材质球太多 private void ChangeSkybox(M ...

  3. WPF-学习笔记 动态修改控件Margin的值

    原文:WPF-学习笔记 动态修改控件Margin的值 举例说明:动态添加一个TextBox到Grid中,并设置它的Margin: TextBox text = new TextBox(); t_gri ...

  4. WPF MVVM 验证

    WPF MVVM(Caliburn.Micro) 数据验证 书接前文 前文中仅是WPF验证中的一种,我们暂且称之为View端的验证(因为其验证规是写在Xaml文件中的). 还有一种我们称之为Model ...

  5. WPF MVVM初体验

    首先MVVM设计模式的结构, Views: 由Window/Page/UserControl等构成,通过DataBinding与ViewModels建立关联: ViewModels:由一组命令,可以绑 ...

  6. WPF/MVVM 快速开始指南(译)(转)

    WPF/MVVM 快速开始指南(译) 本篇文章是Barry Lapthorn创作的,感觉写得很好,翻译一下,做个纪念.由于英文水平实在太烂,所以翻译有错或者译得不好的地方请多指正.另外由于原文是针对W ...

  7. WPF中动态更新TextBlock文字中的超链接,文本

    1.------------------------------------------------------------------------- 修改超链接的文本文字: <TextBloc ...

  8. WPF MVVM使用prism4.1搭建

    WPF MVVM使用prism4.1搭建 MVVM即Model-View-ViewModel,MVVM模式与MVP(Model-View-Presenter)模式相似,主要目的是分离视图(View)和 ...

  9. ViewModel从未如此清爽 - 轻量级WPF MVVM框架Stylet

    Stylet是我最近发现的一个WPF MVVM框架, 在博客园上搜了一下, 相关的文章基本没有, 所以写了这个入门的文章推荐给大家. Stylet是受Caliburn Micro项目的启发, 所以借鉴 ...

随机推荐

  1. 使用nginx生成缩略图

    nginx中可以使用 --with-http_image_filter_module 这个模块,今天发现在github上发现国人开发的一款模块 模块同时支持 Nginx 和 tengine 本ngin ...

  2. Mac环境 MySQL 和 MySQLWorkBench 破解版百度云下载

    最近有小伙伴下载,我正好保存有 正好分享一下 下载路径: Max环境下下载安装 1.下载完直接安装 MySQL安装后,这里可以查看 2.MySQLWorkBench安装完,桌面会有图标 打开后,用lo ...

  3. Notepad++的json 格式化

      1. 打开nodepad++   2. 找到JSON Viewer 点击右上角"安装", 会有提示框安装重启notepad++, 点击ok    3. 自动重启后, 就可以看到 ...

  4. HDUOJ-----2065"红色病毒"问题

    "红色病毒"问题 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  5. [转]一千行MySQL学习笔记

    Shocker /* 启动MySQL */ net start mysql /* 连接与断开服务器 */ mysql -h 地址 -P 端口 -u 用户名 -p 密码 /* 跳过权限验证登录MySQL ...

  6. linux命令中的 < 和 |、>符号作用就解释

    输出重定向比如输入一条命令,默认行为是将结果输出到屏幕.但有时候我们需要将输出的结果保存到文件,就可以用重定向.ps > ps.txt < 表示的是输入重定向的意思,就是把<后面跟的 ...

  7. 主流ETL(Extract-Transform-Load)工具选型,Kettle Spoon、Datastage、Powercenter介绍

    参考:三大主流ETL工具选型 ETL工具 Kettle Spoon 开源ETL工具,所以免费,用java开发的. Ascential公司的Datastage(在2005年被IBM收购现在是 IBM 的 ...

  8. 越狱iphone在cydia下插件后出现exit safe mode肿么办小教程

    http://bbs.app111.com/thread-318898-1-1.html 从简单的开始..最简单的点击状态栏会弹出来一个窗口,那窗口有三个选择请选择第二个,然后等待它重启,重启后还没消 ...

  9. C# 默认参数/可选参数需要注意

    在使用C#的默认参数/可选参数的时候,需要注意,参数的默认值是在编译的时候,自动加入调用方的. 如我有这样一个方法: public class Name { public void Test(Bool ...

  10. ASP.NET MVC ajax处理 AjaxResult

    1.统一ASPNET MVC 对ajax请求响应格式定义,方便前端统一处理ajax结果. 1)定义程序返回结果数据格式 /// <summary> /// 执行结果 /// </su ...