WPF MVVM LISTBOX批量多嵌套控件双向动态数据

Mvvm UI设计

本人在日常工作中记录的日记总结,希望能给大家带来一些乐趣!

Listbox

ListBox是我们在WPF中很常见功能很强大的一个控件,我们会经常使用它来生成符合项目需求的数据显示。以下就是我当前遇到的一种:

  1. 界面存在多控件嵌套如何实现动态View,ViewModel绑定 :

分解功能

1.1.搭建Model
1.2.创建View
1.3.实现逻辑ViewModel

容易卡点的地方

2.在ViewModel中修改数据源后,由于嵌套控件的原因实时数据无法同步到前端
这个时候就需要使用到INotifyPropertyChanged接口,当属性发生改变时,捕获改变并同步变化。

2.1在ViewModel类中重写实现同步功能需要的方法并绑定数据源

namespace Client.ViewModels
{
    public class DataViewModel : ViewModelBase  //ViewModelBase(继承,请借鉴Model写法)INotifyPropertyChanged
    {
	    public DataViewModel ()
		{
	   
		}
        static DataViewModel  _instance;
        public static DataViewModel   Instance
        {
            private set
            {
                _instance = value;
            }
            get
            {
                if (_instance == null)
                {
                    _instance = new DataViewModel  ();
                }
                return _instance;
            }
        }
         private ObservableCollection<DataModel> _dataList;
		 public ObservableCollection<DataModel> DataList
		 {
			     get { return _dataList; }
			     set
			     {
			         _dataList= value;
			         OnPropertyChanged(nameof(DataList));
			     }
		 }
   }
}

2.2Model代码

将需要实时动态同步的属性绑定

//Description实时变化
namespace Client.Models
{
    public class DataModel: INotifyPropertyChanged
    {
        public string IsShow{ get; set; }
        public string Person { get; set; }
        public string Name { get; set; }
        private string _description;
		public string Description
		{
		    get { return _description; }
		    set
		    {
		        _description = value;
		        OnPropertyChanged(nameof(Description));
		    }
		}
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

View片段代码1

将需要实时动态同步的属性绑定

<UserControl x:Class="Client.Views.ListBoxDemoView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
             xmlns:local="clr-namespace:Client.Views"
             xmlns:vm="clr-namespace:Client.ViewModels"
             xmlns:prism="http://prismlibrary.com/"
             mc:Ignorable="d" 
            > 
    <UserControl.Resources>
        <share:BooleanToVisibleConverter x:Key="IsVisable"/>
        <share:BoolValueOppositeConverter x:Key="IsEnable"/>
    </UserControl.Resources>
  <ListBox  SelectedItem="{Binding SelectedItem}" 
	  MaxHeight="900" Background="#ECECEC" 
	  BorderThickness="1" BorderBrush="Black" 
	  ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" 
	  ItemsSource="{Binding DataList,NotifyOnSourceUpdated=True ,Mode=TwoWay}" >
  </ListBox>
 </UserControl>

View片段代码2

将需要实时动态同步的属性绑定

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="ListBox">
        <Setter Property="Background" Value="White" />
        <Setter Property="BorderThickness" Value="0" />
    </Style>
    <Style TargetType="ListBoxItem">
        <Setter Property="Margin" Value="0 8"/>
        <Setter Property="Background" Value="White" />
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Grid >
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition MinWidth="777" ></ColumnDefinition>
                            <ColumnDefinition MinWidth="200" ></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <Border  Grid.Column="0" BorderBrush="#B3B3B3" BorderThickness="1 1 0 1" >                         
                        <Grid>
                                <TextBlock 
                                    FontSize="24"  
                                    Height="75"
                                    Padding="30 25 0 0"
                                    Text="{Binding Description}" />
                         </Grid>
                        </Border>
                       <Border  Grid.Column="1" BorderBrush="#B3B3B3" BorderThickness="1 1 0 1" >                   
                       <Grid>
                                <TextBlock 
                                    FontSize="24"  
                                    Height="75"
                                    Padding="30 25 0 0"
                                    Text="{Binding Name}" />
                       </Grid>
                       </Border>
                    </Grid>
                </DataTemplate>
            </Setter.Value>
        </Setter>
        //设置显示条件
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding Path=IsShow}" Value="True"/>
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.Setters>
                    <Setter Property="Background" Value="Gray"/>
                </MultiDataTrigger.Setters>
            </MultiDataTrigger>
        </Style.Triggers>
    </Style>
</ResourceDictionary>

若使用其它控件包括但不限于Button、Combox 、CheckBox等command事件出现无法进入命令的情况,可以尝试在控件属性中设置

Command="{Binding  DataContext.NameCommand , RelativeSource={RelativeSource AncestorType={x:Type ListBox}}, Mode=TwoWay}" 
CommandParameter="{Binding}" ## 标题

对于初学者容易忽略的地方

xaml.cs 中视图与数据绑定

namespace Client.Views
{
    /// <summary>
    /// ListBoxDemoView.xaml 的交互逻辑
    /// </summary>
    public partial class ListBoxDemoView: UserControl
    {
        public ListBoxDemoView()
        {
            InitializeComponent();
            DataContext = DataViewModel.Instance;
        }
    }
}

总结关键点

1.View与ViewModel 数据的绑定 .xaml.cs 与ViewModel的Context关联
2.ViewModel获取数据变化 继承INotifyPropertyChanged 重写OnPropertyChanged
3. Model中的属性变化获取
ps. 也可以使用 Button Combox 等控件批量生成噢。建议ViewModel 写一个底层通用ViewModelBase 继承必要的接口 降低代码重复率
4.本人水平有限,有不到之处请多指教!
[1]: http://meta.math.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference
[2]: https://mermaidjs.github.io/
[3]: https://mermaidjs.github.io/
[4]: http://adrai.github.io/flowchart.js/

WPF MVVM模式中,可以通过在ViewModel中使用ObservableCollection来动态添加自定义控件。ObservableCollection是.NET Framework提供的一个集合类,它能够在集合元素发生变化时自动通知界面进行更新。 首先,在ViewModel中声明一个ObservableCollection属性,用于存储自定义控件的集合。然后,在需要添加自定义控件的地方,通过操作ObservableCollection来添加新的控件。ViewModel会自动通知界面进行更新。 接下来,界面需要绑定这个ObservableCollection属性,并使用数据模板来定义如何渲染每个自定义控件。在XAML中,可以使用ItemsControl或者ListBox控件来展示这个集合,并通过绑定将集合和数据模板关联起来。 在这个过程中,可以根据需要使用拖放、缩放、旋转等功能。可以参考中的示例代码,了解如何实现这些功能。 最后,通过实例化ViewModel,并将其赋值给界面的DataContext属性,从而建立ViewModel和View之间的关联。可以参考中的代码。 总结起来,实现在WPF MVVM模式中动态添加自定义控件的步骤为: 1. 在ViewModel中声明一个ObservableCollection属性,用于存储自定义控件的集合; 2. 在需要添加自定义控件的地方,通过操作ObservableCollection来添加新的控件; 3. 在界面中,绑定这个ObservableCollection属性,并使用数据模板来定义如何渲染每个自定义控件; 4. 根据需要使用拖放、缩放、旋转等功能; 5. 实例化ViewModel,并将其赋值给界面的DataContext属性,建立ViewModel和View之间的关联。 希望这个实现思路对你有帮助,如果需要更详细的代码示例,可以参考中的文章。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [用WPF mvvm如何动态添加自定义控件问题](https://blog.csdn.net/netyou/article/details/104371498)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [WPF Prism MVVM【动态添加控件并可用鼠标、拖动、缩放、旋转】](https://blog.csdn.net/redfox6843/article/details/126117819)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值