Model-View-ViewModel(MVVM)是一种架构设计模式,用于实现用户界面,通过其表示逻辑(其ViewModel)将UI(View)与其数据(Model)分开。
如何在 Android 电子商务应用程序中同步数据检索和 UI 更新?
我正在开发一个用于电子商务的 Android 应用程序,我面临着一个挑战,即在完全检索所需数据之前创建用户界面。结果,应用程序不显示...
MAUI:在页面之间导航的 GoToAsync() 和 PushAsync() 有什么区别?
我正在尝试了解如何在 MAUI 应用程序和 MVVM 的页面之间导航的最佳方式。 我在 Microsoft 的示例中看到,默认方法是使用 PushAsync(),但是...
我在当前的 WPF 项目中使用 MVVM Light,我想知道什么时候应该使用 MVVM Light 的消息传递而不是 WPF 事件。 WPF 事件: 我的控件.xaml 我在当前的 WPF 项目中使用 MVVM Light,我想知道什么时候应该使用 MVVM Light 的消息传递而不是 WPF 事件。 WPF 事件: MyControl.xaml <ListView SelectionChanged="ListView_OnSelectionChanged" /> MyControl.cs private MyViewModel ViewModel { get { return this.DataContext as MyViewModel; } } private void ListView_OnSelectionChanged( object sender, SelectionChangedEventArgs e ) { this.ViewModel.ListViewSelectionChanged( ( (ListView) sender ).SelectedItems ); } MVVM 轻消息传递: MyControl.cs private void ListView_OnSelectionChanged( object sender, SelectionChangedEventArgs e ) { Messenger.Default.Send( new ListViewSelectionMessage {SelectedItems = ((ListView)sender).SelectedItems} ); } ListViewSelectionMessage.cs public class ListViewSelectionMessage { public IList SelectedItems { get; set; } } 我的视图模型 public class MyViewModel { MyViewModel() { Messenger.Default.Register<ListViewSelectionMessage>(this, this.ListViewSelectionChaged); } private void ListViewSelectionChaged( ListViewSelectionMessage message ) { // ... } } 因为使用 Messenger,一切都可以很容易地解耦,所以我很想在任何地方都使用 Messenger。使用 Messenger 而不是 Events 有什么问题吗?或者这会产生我不知道的问题。谢谢! 通常,任何 MVVM 框架(Prism、MVVM Light)中的消息都是在具有插件架构的应用程序中的松散耦合组件之间进行通信的好方法,因为您可以通过共享库中声明的合约将消息从一个模块发送到另一个模块。当您单独开发应用程序或在小团队中由高技能程序员开发应用程序时,可以使用它。 否则有一个主要缺点:重构和调试非常困难,因为你不能只点击消息并“查找用法”,你需要先去合约(接口)而不是“查找用法”,然后直观地查找带有订阅/注册指令的地方。此外,开发人员通常会忘记取消订阅消息,因此您将面临问题,即从一个模块发送并打算在同一模块中处理的消息将在其他模块中错误地处理,因此会导致意外行为并产生许多令人痛苦的错误。 以上内容均基于我的个人经验,因此结果可能会有所不同。只要小心消息,它就会对你有好处。另外,在我看来,消息作为事件的替代品有点开销/过度设计,因为当您拥有紧密耦合的组件时,您并不真正需要它。 2024 年更新,随着 MVVMLight 被弃用,MVVM Toolkit(其精神继承者)具有 Messenger 类:https://learn.microsoft.com/dotnet/communitytoolkit/mvvm/messenger 性能基准:https://devblogs.microsoft.com/dotnet/announcing-the-dotnet-community-toolkit-800/#improved-messenger-apis-📬
MAUI 中使用 ObservableObject 自动重置 Observable 属性
我是 MAUI 新手,正在尝试使用 MVVM 模型。 我有一个 viewModel BLEDeviceViewModel、一个视图 MachineSelect 和一个模型 BLEDevice。 在 MachineSelect.xaml.cs 中,我有以下代码: 公开
我正在寻找有关处理 wpf mvvm 项目中越来越多的命令的建议。 我的视图模型收集了大量的模型,我觉得在项目成熟之前我需要做
我有一个视图模型,它有一个网络服务,可以返回一个组合发布者。 VM 通过更新其状态来对该发布者做出反应。然后 UIViewController 将根据 VM 进行更新
在WinUI3项目中,我有3个视图IconEditorView、ColorEditorView和ImageEditorView,每个视图都有对应的ViewModel IconEditorViewModel、ColorEditorViewModel和ImageEditorViewModel...
我有一个关于 C#/WPF 的 MVVM 设计的问题。我看过几个演示应用程序,但它们并没有真正解决我的问题。 我的应用程序由包含其他对象的对象组成
如何在WPF MVVM项目中通过ViewModel共享数据?
我正在通过做一个简单的应用程序来学习WPF,更一般地说是MVVM。 我的主窗口包含 4 个视图。 一个用于主功能区,存储一些用户参数,一个用于设计表,
在一个 MainViewModel 中我发送一条消息: 私有无效 TextBoxKeyDownVMMethod(KeyEventArgs e) { if (e.Key == Key.Enter) { MessengerInstance.Send 在一个 MainViewModel 中我发送一条消息: private void TextBoxKeyDownVMMethod(KeyEventArgs e) { if (e.Key == Key.Enter) { MessengerInstance.Send<Messages.WebTab.NavigatingToPageArgs>(new NavigatingToPageArgs { UrlForNavigating = "http://stackoverflow.com/questions/11485897/viewmodel-doesnt-receive-message-in-mvvm-light" }); //GoToPageInSelectedTabVMCommand.Execute((object)null); Keyboard.ClearFocus(); } } 在另一封邮件中我收到了它: public WebTabItemVievModel() { MessengerInstance.Register<NotificationMessage<Messages.WebTab.NavigatingToPageArgs>>(this, _MessageHandler_NavigatingToPage); } private void _MessageHandler_NavigatingToPage(NotificationMessage<NavigatingToPageArgs> args) { GoToPageCommand.Execute(args.Content.UrlForNavigating); } WebTabItemVievModel 在 MainViewModel 的构造函数中创建为 ObservableCollection, 这个集合是选项卡控件的 ItemsSource public MainViewModel() { WebTabItems = new ObservableCollection<WebTabItemVievModel>(); WebTabItemVievModel tabItem; tabItem = ServiceLocator.Current.GetInstance<WebTabItemVievModel>(); tabItem.Header = "Empty tab"; WebTabItems.Add(tabItem); tabItem = new WebTabItemVievModel { Header = "Empty tab" }; WebTabItems.Add(tabItem); tabItem = new WebTabItemVievModel { Header = "Empty tab" }; WebTabItems.Add(tabItem); tabItem = new WebTabItemVievModel() { AddNewTabOnTabHeaderClick =true}; WebTabItems.Add(tabItem); } WebTabItemVievModel 有自己的用于可视化的 UserControl,它通过 MainWindow.xaml 中的资源定义进行绑定: <Window.Resources> <DataTemplate DataType="{x:Type vm:WebTabItemVievModel}" > <v:WebTabItemContentViev></v:WebTabItemContentViev> </DataTemplate> </Window.Resources> Locator 在注册时已经有 true 参数。它没有改变任何东西: SimpleIoc.Default.Register<WebTabItemVievModel>(true); SimpleIoc.Default.Register<MainViewModel>(true); 谁知道为什么 WebTabItemVievModels 不接收消息? 注册类型时 通知消息 但是发送时类型是 Messages.WebTab.NavigatingToPageArgs 使类型相同,它应该可以工作
如何使用 MVVM 在 WPF 中正确实现导航侧边栏菜单(+找出更改应用程序中视图的正确方法)?
如果有人可能觉得标题令人困惑,我想道歉,我在这里描述的问题比我想象的要复杂,我很难在标题中总结它。 基础...
如何使用 WinUI 模式的模板 datastudio 从视图模型自动滚动数据网格
您能否帮助我了解如何在处理视图模型中的列表时自动滚动数据网格列表。 这是一个想法,我有一个加载到数据网格的项目列表,然后按
是否有 MVVM 方式(使用 ViewModel)在 XAML 中为 DataGrid 列(DataGridTextColumn 等)使用 x:bind? 我见过的所有代码都使用 Binding 而不是 x:Bind。
我正在 VS 22 中使用 .Net MAUI 制作一个应用程序,我设置了一个简单的页面,在其中显示项目列表,但是当我尝试运行代码时,出现此错误: 严重性代码描述项目文件Li...
正在制作 .Net MAUI 应用程序并遇到了我无法解决的问题
我正在 VS 22 中使用 .Net MAUI 制作一个应用程序,我设置了一个简单的页面,在其中显示项目列表,但是当我尝试运行代码时,出现此错误: 严重性代码描述项目文件Li...
如何使用 WPF 中 MVVM 模式中的当前终端更新我的 TerminalList-View?我将 List _terminals 传递给 ViewModel,但我不知道如何将其分配给可观察的集合...
MAUI - 绑定到集合中的嵌套属性。 Markdown 中的 OnPropertyChanged 中继
我的设置非常复杂,而且我遗漏了一些东西。绑定正在工作,但当我调用 UpdateValue 方法时,OnPropertyChanged 不会刷新视图。 当我收到一条消息时...
我有一个 xaml 脚本,它不会监听 OnPropertyChanged。初始化视图时,它可以正常工作,但我无法更新它。 零件.xaml: 我有一个 xaml 脚本,它不会监听 OnPropertyChanged。初始化视图时,它可以正常工作,但我无法更新它。 零件.xaml: <UserControl x:Class="Page_Navigation_App.View.Parts" 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:vm="clr-namespace:Page_Navigation_App.ViewModel" xmlns:utils="clr-namespace:Page_Navigation_App.Utilities" mc:Ignorable="d" d:DesignHeight="600" d:DesignWidth="622" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Style="{StaticResource Page_Style}"> <UserControl.DataContext> <vm:PartsVM x:Name="_model"/> </UserControl.DataContext> ..... <Grid Margin="15"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="5" /> <!-- Width for the splitter --> <ColumnDefinition Width="*" /> <!-- Width of the details pane --> </Grid.ColumnDefinitions> <!-- ListView for Parts or Variants --> <ListView ItemsSource="{Binding TableData}" SelectedItem="{Binding SelectedPart, Mode=TwoWay}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="0" Margin="0,0,0,10" Visibility="{Binding PartsVisibility}"> <ListView.ItemTemplate> <DataTemplate> <!-- Card Container --> <Border Background="#343a40" CornerRadius="10" Padding="10" BorderBrush="#3C3F41" BorderThickness="1" Margin="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.ColumnSpan="3" Width="Auto" > <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <!-- Define rows for labels, values, and button --> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <!-- ID Field --> <TextBlock Text="Image:" FontWeight="Bold" Foreground="White" Margin="0,0,10,0" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Stretch" /> <TextBlock Text="{Binding [ID], UpdateSourceTrigger = PropertyChanged}" Foreground="White" Margin="0,0,20,0" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Stretch" /> <!-- Description Field --> <TextBlock Text="Description:" FontWeight="Bold" Foreground="White" Margin="0,0,10,0" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Stretch" /> <TextBlock Text="{Binding [Description],UpdateSourceTrigger=PropertyChanged}" Foreground="White" Margin="0,0,20,0" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Stretch" /> <!-- Additional Details (Optional) --> <TextBlock Text="Type:" FontWeight="Bold" Foreground="White" Margin="0,0,10,0" Grid.Column="2" Grid.Row="0" Visibility="{Binding [Type], Converter={StaticResource StringToVisibilityConverter} }" HorizontalAlignment="Stretch" /> <TextBlock Text="{Binding [Type] , UpdateSourceTrigger=PropertyChanged}" Foreground="White" Margin="0,0,20,0" Grid.Column="2" Grid.Row="1" Visibility="{Binding [Type], Converter={StaticResource StringToVisibilityConverter}}" HorizontalAlignment="Stretch" /> <!-- Button --> <Button Content="Variants" Command="{Binding DataContext.ShowVariantsCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}} , UpdateSourceTrigger=PropertyChanged}" CommandParameter="{Binding}" Grid.Column="3" Grid.Row="0" Grid.RowSpan="3" VerticalAlignment="Stretch" Margin="0,10,0,0" HorizontalAlignment="Stretch" Padding="5,2"/> </Grid> </Border> </DataTemplate> </ListView.ItemTemplate> </ListView> Parts.xaml.cs: namespace Page_Navigation_App.View { /// <summary> /// Interaction logic for Customers.xaml /// </summary> public partial class Parts : UserControl { //private PartsVM _model = new PartsVM(); public Parts() { InitializeComponent(); //DataContext = new PartsVM(); } } } PartsVM.cs: using Microsoft.Data.SqlClient; using Page_Navigation_App.Utilities; using System; using System.Collections.ObjectModel; using System.Data; using System.Linq; using System.Windows; using System.Windows.Input; namespace Page_Navigation_App.ViewModel { class PartsVM : Utilities.ViewModelBase { private readonly DBHandler _dbHandler; private static string TCPServer = "*****"; private static string DBCatalog = "*****"; private string _test; //private DBHandler dbHandler; private SqlConnection _sqlConnection; private ObservableCollection<DataRow> _tableData; private DataRow _selectedPart; private ObservableCollection<Variant> _variants; private bool _isViewingVariants; private Visibility _partsVisibility; private Visibility _reversePartsVisibility = Visibility.Collapsed; private ObservableCollection<EndUser> _endUsers; private string tableName = "Sales.Parts"; // Define column names at the class level private readonly ObservableCollection<string> columnNames = new ObservableCollection<string> { "ID", "Description", "Type", "Comment" }; int i = 0; public ObservableCollection<EndUser> EndUsers { get { return _endUsers; } set { _endUsers = value; OnPropertyChanged(nameof(EndUsers)); } } public ObservableCollection<DataRow> TableData { get { return _tableData; } set { _tableData = value; OnPropertyChanged(nameof(TableData)); } } public string Test { get { return _test; } set { _test = value; OnPropertyChanged(nameof(Test)); } } public DataRow SelectedPart { get { return _selectedPart; } set { _selectedPart = value; OnPropertyChanged(); } } public ObservableCollection<Variant> Variants { get { return _variants; } set { _variants = value; OnPropertyChanged(); } } public bool IsViewingVariants { get { return _isViewingVariants; } set { _isViewingVariants = value; OnPropertyChanged(); } } public Visibility PartsVisibility { get { return _partsVisibility; } set { _partsVisibility = value; OnPropertyChanged(); } } public Visibility ReversePartsVisibility { get { return _reversePartsVisibility; } set { _reversePartsVisibility = value; OnPropertyChanged(); } } public ICommand ShowVariantsCommand { get; set; } public ICommand BackToPartsCommand { get; set; } public PartsVM() { _tableData = new ObservableCollection<DataRow>(); SQLConnectionManager.Initialize(); _sqlConnection = SQLConnectionManager.GetConnection(); if (_sqlConnection == null) { throw new InvalidOperationException("Database connection is not initialized."); } _dbHandler = new DBHandler(_sqlConnection); GetAll(); //Search("test"); } public void GetAll() { i++; string query = $"SELECT * FROM {tableName};"; var dataTable = new DataTable(); using (var command = new SqlCommand(query, _sqlConnection)) { using (var adapter = new SqlDataAdapter(command)) { // Fill the DataTable with the result of the query adapter.Fill(dataTable); } } this.Test = i.ToString(); // Convert DataTable rows to ObservableCollection<DataRow> var rows = new ObservableCollection<DataRow>(dataTable.AsEnumerable()); // Clear the existing TableData and add the new rows TableData.Clear(); /*foreach (var row in rows) { TableData.Add(row); }*/ TableData = rows; // Notify that TableData has changed //OnPropertyChanged(nameof(TableData)); } public void Search(string searchTerm) { // Escape special characters in searchTerm for SQL LIKE string escapedSearchTerm = "%" + searchTerm + "%"; // Generate the LIKE clause for each column string likeClause = string.Join(" OR ", columnNames.Select(col => $"{col} LIKE @searchTerm")); string query = $"SELECT * FROM {tableName} WHERE {likeClause};"; //MessageBox.Show(query); var dataTable = new DataTable(); using (var command = new SqlCommand(query, _sqlConnection)) { // Add the parameter once to be used in all LIKE statements command.Parameters.AddWithValue("@searchTerm", escapedSearchTerm); using (var adapter = new SqlDataAdapter(command)) { // Fill the dataTable with the query result adapter.Fill(dataTable); } } var rows = new ObservableCollection<DataRow>(dataTable.AsEnumerable()); int test = TableData.Count; // Convert DataTable rows to an ObservableCollection of DataRow TableData.Clear(); foreach (DataRow row in rows) { TableData.Add(row); } TableData = rows; } } } ViewmodelBase: namespace Page_Navigation_App.Utilities { class ViewModelBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName] string propName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName)); } } } 我知道函数被触发了,因为我已经调试过了。 搜索功能由不同脚本中的函数触发。我还知道 DataTable 正在正确更新,但 UI 不会更新。我尝试手动触发 PropertyChanged,无论是否显式设置 UpdateSourceTrigger。 我不知道为什么这不起作用。预先感谢 您使用的语法无效,这里正确的绑定语法是: <TextBlock Text="{Binding ID}" />
Android Fragment LiveData 仅在屏幕旋转或配置更改后更新 - 使用 Java
我正在构建一个 Android 应用程序,用于显示从 API 获取的天气数据。我使用 WeatherViewModel 和 LiveData 来保留配置更改中的数据并确保其显示在
Command<int> CanExecute 在 WPF 视图中无法正常工作
我目前正在处理 WPF 屏幕的视图,其中我们遇到了 Command 或 Command 类型的命令的异常问题。 在我们的应用程序中,有一个带有