Xamarin 条目绑定到 MVVM

Posted

技术标签:

【中文标题】Xamarin 条目绑定到 MVVM【英文标题】:Xamarin Entry Binding to MVVM 【发布时间】:2021-10-16 10:22:34 【问题描述】:

我正在尝试使用 MVVM 而不是背后的代码来实现我所能做的一切,但如果我有很多对象需要在条目更改时访问,我根本不知道如何做好。

Xaml:

<Entry x:Name="UpdatedCost"                       
       TextChanged="UpdatedCost_TextChanged"/>

<Label x:Name="PriceDifLabel"/>

<Entry x:Name="CurrentCost"
       Text="2.5"/>

<Entry x:Name="CurPriceUpdatedCostProfit"
        Text="22%"/>

代码隐藏:

private void UpdatedCost_TextChanged(object sender, TextChangedEventArgs e)
        
            if (double.TryParse(e.NewTextValue, out double UpdatedCost))
            
                double diff = UpdatedCost - double.Parse(CurrentCost.Text);
                string sign = diff > 0 ? "+" : "";
                PriceDifLabel.Text = "(" + sign + string.Format("0:0.0", diff) +")";
                PriceDifLabel.TextColor = diff > 0 ? Color.Red : Color.Green;
                PriceDifLabel.BackgroundColor = Color.Yellow;
                CurPriceUpdatedCostProfit.Text = ((int)((double.Parse(CurrentPrice.Text) - UpdatedCost) /
                                                   double.Parse(CurrentPrice.Text) * 100)).ToString() + "%";
            
            
            
        

我非常感谢尽可能详细的帮助将此方法转换为 MVVM 实现。如果相关,我的视图模型正在实现 MvvmHelpers 的 BaseViewModel。

非常感谢!

【问题讨论】:

我会为您的特殊格式和内容创建一个正面标签和另一个负面差异标签。然后,您可以将 IsVisible 属性绑定到 VM 中的某个属性,该属性决定它的价格是更高还是更低。 到底是什么问题?对我来说,这看起来像是“将其转换为 MVVM”编码请求。您是否尝试过创建属性、绑定它们、从另一个属性设置器更改/增加一个属性的通知等? 感谢 cmets。是的,我确实尝试过,但我是一个初学者,所以有很多问题,尤其是它是一个条目,我需要它的值和其他值。 CurrentPrice.Text 是什么?它是一个常数吗? currentcost.text 也是常数吗? 【参考方案1】:

是的,您可以创建模型并为不同的控件创建不同的属性。 我根据您的代码创建了一个简单的演示(以PriceDifLabel 的文本和文本颜色为例)。

可以参考以下代码:

1.创建模型MyViewModel.cs并实现接口INotifyPropertyChanged

而当我们改变UpdatedCost的值时(bind for Entry UpdatedCost),我们也可以相应地改变PriceDif

MyViewModel.cs

   public class MyViewModel: INotifyPropertyChanged
    
        double _updatedCost;
        public double UpdatedCost
        
            set  
                SetProperty(ref _updatedCost, value);
                double diff = UpdatedCost - double.Parse(CurrentCost);
                string sign = diff > 0 ? "+" : "";

                PriceDif = "(" + sign + string.Format("0:0.0", diff) + ")";

                PriceDifLabelColor = diff > 0 ? Color.Red : Color.Green;

                System.Diagnostics.Debug.WriteLine("----------> PriceDif = " + PriceDif);
            

            get  return _updatedCost; 
        

        string _currentCost;
        public string CurrentCost
        
            set  SetProperty(ref _currentCost, value); 

            get  return _currentCost; 
        


        string _priceDif;
        public string PriceDif
        
            set  SetProperty(ref _priceDif, value); 

            get  return _priceDif; 
        

        Color _priceDifLabelColor = Color.Green;
        public Color PriceDifLabelColor
        
            set  SetProperty(ref _priceDifLabelColor, value); 

            get  return _priceDifLabelColor; 
        
 
        public MyViewModel() 
            CurrentCost = "2.5";
           

        bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        
            if (Object.Equals(storage, value))
                return false;

            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        

        public event PropertyChangedEventHandler PropertyChanged;
    

2.在page.xaml中绑定这些属性

<?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:testapp1="clr-namespace:TestApp1"
             x:Class="TestApp1.TestPage2">

    <ContentPage.BindingContext>
        <testapp1:MyViewModel></testapp1:MyViewModel>
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout>
            <Entry x:Name="UpdatedCost" Text="Binding UpdatedCost" />

            <Label x:Name="PriceDifLabel" Text=" Binding PriceDif" TextColor="Binding PriceDifLabelColor"/>

            <Entry x:Name="CurrentCost" Text="2.5"/>

            <Entry x:Name="CurPriceUpdatedCostProfit" Text="22%"/>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

更多关于INotifyPropertyChanged接口,可以查看:

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/binding-mode#viewmodels-and-property-change-notifications.

【讨论】:

非常感谢您的详细解答!【参考方案2】:

1.您好,您可以创建这个BaseViewModel,然后将其传递给每个ViewModel,那么您不必总是为每个ViewModel单独创建INotifyPropertyChanged接口。 然后你可以像这里一样将它继承到任何 ViewModel:

    using YourApp.ViewModels
    ...
    public class YourViewModel : BaseViewModel 
    ....
    
    //This is the BaseViewModel:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;


    namespace YourApp.ViewModel
    
    public abstract class BaseViewModel : INotifyPropertyChanged
    
    //declares the (required) PropertyChanged event that is defined by 
    //the interface.
    public event PropertyChangedEventHandler PropertyChanged;
    // next it is checked if someone has registered for the event,
    // and in this case the event will be raised with the name of the 
    //property being updated.
    protected void OnPropertyChanged([CallerMemberName] string 
    propertyName = "")
    
        var changed = PropertyChanged;
        if (changed == null)
            return;

        changed.Invoke(this, new 
    PropertyChangedEventArgs(propertyName));
    
    // This is a helper method to make setting the property easier. 
    // Right now you can just take this with faith
    // or if you are familiar with generics you can study it a little to 
    // see how it works.
    protected bool SetProperty<T>(ref T backingStore, T value,
       [CallerMemberName] string propertyName = "",
       Action onChanged = null)
    
        if (EqualityComparer<T>.Default.Equals(backingStore, value))
            return false;

        backingStore = value;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
        return true;
    


【讨论】:

以上是关于Xamarin 条目绑定到 MVVM的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin 表单清除所有条目

Xamarin.Forms 条目 - 自定义行为和 MVVM

Android--ListView与数据绑定(Xamarin)

在 Xamarin 中动态更改条目输入的 Tab 键顺序

达到条目最大长度时的 Xamarin DisplayAlert

Xamarin Forms - 否定布尔绑定值