gpt4 book ai didi

c# - View 不会被模型更新

转载 作者:太空宇宙 更新时间:2023-11-03 12:13:38 25 4
gpt4 key购买 nike

对于这个冗长的问题,我深表歉意,但我希望你能坚持下去。我已尽力包含所有相关代码片段,以便准确解释我想要实现的目标。

我正在尝试将我的移动应用程序转换为 MVVM 设计模式,但我在根据模型中发生的更改更新 View 时遇到了一些困难。

我已将我的应用程序拆分为经典的模型、 View 、 View 模型结构。

目前,我正在尝试从我的模型 SoundScapeData.cs 传播数据我的观点HomePage.xaml .

我的 HomePage.xaml代码隐藏文件如下所示:

namespace AX2018
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class HomePage : ContentPage
{
public HomePage()
{
InitializeComponent();
BindingContext = new HomePageViewModel();
}

private void OnConnectButtonClicked(object sender, EventArgs e)
{
Bluetooth bluetooth = new Bluetooth();
bluetooth.Connect();
}
}
}

如您所见,我使用 BindingContext 绑定(bind)我的数据关键字并将其绑定(bind)到 HomePageViewModel 的新实例类。

我正在连接蓝牙设备,因此调用 bluetooth.Connect()在点击 Button 时调用在HomePage.xaml看法。然后,此蓝牙设备使用特定值更新应用程序。

我想强调的是,蓝牙连接运行良好,并且已经过验证可以在转换为 MVVM 设计模式之前与 View 一起工作。

我的 ViewModel,HomePageViewModel.cs ,看起来像这样:

namespace AX2018
{
public class HomePageViewModel
{
private SoundScapeData _soundScapeData;

public SoundScapeData SoundScapedata { get { return _soundScapeData; } }

public HomePageViewModel()
{
_soundScapeData = new SoundScapeData();
}
}
}

附带说明一下,我对如何设计 View 模型有点困惑,因为模型 SoundScapeData.cs目前就是这么简单。这个中间 View 模型是否必要?

这是我的 SoundScapeData.cs型号:

namespace AX2018
{
public class SoundScapeData : INotifyPropertyChanged
{
private double _spl;

public double SPL
{
get { return _spl; }
set
{
_spl = value;
OnPropertyChanged();
}
}

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

从模型中可以看出,它实现了 INotifyPropertyChanged接口(interface),并在方法OnPropertyChanged()中有处理事件的相关函数.

我的看法,HomePage.xaml , 相当冗长 - 它由一个 9 x 3 网格组成,标签放置在特定位置。这些标签应反射(reflect) SoundScapeData.cs 中的值模型(和其他模型,但那是在路上)。以下是相关片段:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:AX2018"
x:Class="AX2018.HomePage">

<ContentPage.BindingContext>
<local:HomePageViewModel/>
</ContentPage.BindingContext>

...

<Label Text="{Binding SoundScapedata.SPL}"
FontSize="68" Style="{StaticResource ColoredLabel}"
Grid.Row="4"
Grid.Column="1"
Margin="-20"></Label>

如您所见,我已经在 View 中绑定(bind)了数据HomePage.xaml查看模型 HomePageViewModel.cs ,其中包含 SoundScapeData.cs 的一个实例模型,它又实现了 INotifyPropertyChanged界面。

据我了解,这是使用 MVVM 设计模式时数据绑定(bind)方面的正确方法。然而,SPL 的变化并没有反射(reflect)在我的 View 中 HomePage.xaml .

我在一个单独的类中更新 SPL 值,Bluetooth.cs , 它继承自 SoundScapeData.cs模型。这是 Connect() 的片段来自 Bluetooth 的方法类:

namespace AX2018
{
public async void Connect()
{
public class Bluetooth : SoundScapeData
...
var dbValue = (double)BitConverter.ToUInt16(temp1, 0) / 256 * 48;
SPL = dbValue;
...
}
}

再次,对于这个相当长的问题,我深表歉意,但我希望有人能指出我做错了什么。我想重申,转换为 MVVM 之前 View 中的 SPL 值确实更新了,所以我的数据绑定(bind)肯定有问题。

提前谢谢你,

汉森

最佳答案

我会在这里回答,因为评论太短无法解释。如果我拼错了一些名字,请原谅:P让我们总结一下您的场景:

  • 主页是您的 View
  • HomePageViewModel 是您的虚拟机
  • SoundScapeData 是您的模型

现在:

主页(查看)

我真的不知道在 Xamarin oyu 中是否必须复制它,请记住您在后面的代码中设置了它。

<ContentPage.BindingContext>
<local:HomePageViewModel/>
</ContentPage.BindingContext>

你也应该改变这个:

<Label Text="{Binding Spl}" <!--You dont need SoundScapeData anymore this is the public VM property -->
FontSize="68" Style="{StaticResource ColoredLabel}"
Grid.Row="4"
Grid.Column="1"
Margin="-20"></Label>

HomePageViewModel

它应该有你需要的尽可能多的属性。假设您的模型只有一个属性 SPL 。这就是您的模型,现在您必须通过 VM 将其放入 View 中。所以你的 VM 应该有一个属性(公共(public)/私有(private))来适应 View 和你的模型。

private string spl;
public string Spl
{
get {return this.spl;}
set
{
if (this.spl != value)
{
this.spl = value;
OnPropertyChanged("SPL);
}

当您单击该按钮并连接到蓝牙或它所做的任何操作时 (;P),因为它会更改模型,您必须更改您的 VM 属性。请记住,您的模型必须与 VM 中的实例相同。

所以...您应该附加到已更改的模型属性,以便更改您的 VM 属性,最好的方法是创建一个类(让我们尽可能多地应用 SOLID)

public class YourNewDataSource
{
#region Attributes

private readonly HomePageViewModel homePageViewModel;

#endregion

#region Public Methods


public YourNewDataSource(HomePageViewModel homePageViewModel)
{
this.homePageViewModel = homePageViewModel;
}

public void Initialize()
{
this.homePageViewModel.SoundScapeData.PropertyChanged += this.OnHomePageModelPropertyChanged;
}

#endregion

#region Event Handlers

private void OnHomePageModelPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "SPL":
this.homePageViewModel.Spl = this.homePageViewModel.SoundScapeData.Spl;
break;
}
}

#endregion
}

现在,当您启动您的应用程序或想要显示您的 View 时,您必须使用您的 VM 创建一个新的 YourNewDataSource:

public HomePage()
{
InitializeComponent();
HomePageViewModel homePageViewModel = new HomePageViewModel();
YourNewDataSource yourNewDataSource = new YourNewDataSource(homePageViewModel)
BindingContext = homePageViewModel;
}

看一看,试一试,问问你是否没有得到我刚刚写在这里的一些 s*** :D


我刚刚查看了您的 bluetooth.Connect 。

我不知道蓝牙类是否必须从 SoundScapeData 继承,但现在它不起作用,因为您在连接时会丢失 VM 的模型。如果您真的不需要从 SoundScapeData 继承,只需将一个参数添加到您的连接方法并将 Vm.SoundScapeData 传递给它即可。

关于c# - View 不会被模型更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50833147/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com