【发布时间】:2018-11-22 19:04:18
【问题描述】:
对于这个冗长的问题,我深表歉意,但我希望你能坚持下去。我已尽力包含所有相关代码 sn-ps 以准确解释我想要实现的目标。
我正在尝试将我的移动应用程序转换为 MVVM 设计模式,但在根据模型中发生的更改更新视图时遇到了一点困难。
我已将我的应用程序拆分为经典的模型、视图、视图模型结构。
目前,我正在尝试将数据从我的模型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 关键字绑定我的数据并将其绑定到HomePageViewModel 类的新实例。
我正在连接到蓝牙设备,因此调用bluetooth.Connect() 会在HomePage.xaml 视图中点击Button 时调用。然后,此蓝牙设备会使用某些值更新应用程序。
我想强调的是,蓝牙连接运行良好,并且已经验证可以在转换为 MVVM 设计模式之前使用 View。
我的 ViewModel HomePageViewModel.cs 如下所示:
namespace AX2018
{
public class HomePageViewModel
{
private SoundScapeData _soundScapeData;
public SoundScapeData SoundScapedata { get { return _soundScapeData; } }
public HomePageViewModel()
{
_soundScapeData = new SoundScapeData();
}
}
}
顺便说一句,我对如何设计视图模型有点困惑,因为模型SoundScapeData.cs 目前是如此简单。这个中间视图模型是否必要?
这是我的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));
}
}
}
从Model中可以看出,它实现了INotifyPropertyChanged接口,并在OnPropertyChanged()方法中有相关的事件处理函数。
我的视图,HomePage.xaml,相当长 - 它由一个 9 x 3 的网格组成,标签放置在某些位置。这些标签应该反映SoundScapeData.cs 模型(和其他模型,但这是未来)中的值。以下是相关的sn-ps:
<?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 HomePage.xaml 中的数据绑定到 View Model HomePageViewModel.cs,该 View Model HomePageViewModel.cs 包含 SoundScapeData.cs Model 的实例,而后者又实现了 INotifyPropertyChanged 接口。
据我了解,在使用 MVVM 设计模式时,就数据绑定而言,这是正确的方法。但是,SPL 的变化并没有反映在我的视图HomePage.xaml 中。
我在一个单独的类Bluetooth.cs 中更新了 SPL 值,该类继承自 SoundScapeData.cs 模型。这是来自Bluetooth 类的Connect() 方法的sn-p:
namespace AX2018
{
public async void Connect()
{
public class Bluetooth : SoundScapeData
...
var dbValue = (double)BitConverter.ToUInt16(temp1, 0) / 256 * 48;
SPL = dbValue;
...
}
}
再次,我为这个相当长的问题道歉,但我希望有人能向我指出我做错了什么。我想重申一下,在转换为 MVVM 之前,视图中的 SPL 值确实更新了,所以我的数据绑定肯定有问题。
提前谢谢你,
kdhansen
【问题讨论】:
-
很好地组合在一起。
-
只是说。在 MVVM 中,VM 使模型适应视图,因此应该实现 INotifyPropertyChanged 的类应该是 VM 而不是模型。该模型“模拟”了一个现实生活中的对象,VM 将其适应于视图。例如,您可以有一个模型 Dog,它具有腿、大小和名称,并且您的 VM 应该具有您需要显示(腿、大小...)或控制(启用的组合框、可见性标志等)的尽可能多的属性。 ) 在你看来。因此,如果您可以根据特定的大小值更改 Dog 的腿,则应该由 VM 来控制它。希望我自己解释一下。
-
@JuanCarlosRodriguez 我明白你的意思。如果我理解正确,将我的
HomePage.xaml的BindingContext设置为我的模型SoundScapeData.cs的实例将正确反映我的HomePage.xaml视图中的更改。我刚刚这样做了,但绑定SoundScapeData.SPL的标签仍未更新。 -
我只是回答你,但有点长,请给我几分钟
-
@JuanCarlosRodriguez 好的,谢谢。
标签: c# xaml mvvm xamarin.forms