2017-12-08 82 views
0

ユーザーに領収書を表示しているページには、小計、税金、合計を記載したセクションがあります。適用される税金は地域によって異なり、販売される製品に基づいているため、このセクションの行数は異なります。私がすることによってこれを達成しましたXamarin.Forms:VIEWにViewModelを呼び出さずにグリッドに行を動的に追加できますか?

GST+PST

GST Only

No Tax

:たとえば、ここでは3つの別々の注文、GSTとPST、ちょうどGSTとの1、と1と1とのどちらもありますXAMLのグリッドにSubTotalだけを配置し、残りをViewModelから呼び出すメソッドのコードビハインドに追加します。しかし、私は実際にこのようにするのは避けたいので、ViewModelにViewを知らせる必要がない、これを達成するアプローチがあるのだろうかと思います。

ListViewは、いくつかの理由のため、ここでは適していません。

  • これらのコントロールは、ScrollViewの内側にあり、そしてあらゆる種類の奇妙な問題の原因ScrollViewの内部ListViewを持ちます。
  • 私は、列をその最も広い要素ほど狭くしておきたいと思います。これはGridで可能ですが、ListViewは何があっても親の全幅を占有します。私は必要もなく、私の行は

選択できるようにするためにしたい、どちらも

  • だから私はListViewを使用してに頼ることなく表示について知るViewModelにせずにこれを行うことができます方法はありますか?

    public class ReceiptPageModel : PageModelBase 
    { 
        private Receipt _receipt; 
        public Receipt Receipt 
        { 
         get => _receipt; 
         private set => Set(ref _receipt, value); 
        } 
    
        public override void Init(object initData) 
        { 
         Receipt = (Receipt) initData; 
         ((ReceiptPage) CurrentPage).AddTaxes(Receipt); 
        } 
    } 
    

    後::前

  • +1

    ですなぜ、それはVMでなければならず、Viewのコードビハインドではないのでしょうか? VMでそれを行うと、MVVMがひどく壊れてしまいます。 Viewのコードは、VMの行数に基づいて更新できないのはなぜですか? – Jason

    +0

    ええ、私は今質問を間違って考えていました。私がしたいのは、ViewModelから行を追加するのではなく、ViewModelにViewを知らせずに行を追加できることです。しかし、今私はそれをこのように見て、解決策は明らかです。とてもありがとう! – Katie

    +0

    GSTとPSTの自動サイズの行を作成して非表示にすることはできませんか? p.s. FreshMvvmを使ってあなたを見てうれしい! –

    答えて

    1

    TotalsGridControlという新しいユーザーコントロールを作成しました。ここにXAMLがあります

    <?xml version="1.0" encoding="UTF-8"?> 
    <Grid xmlns="http://xamarin.com/schemas/2014/forms" 
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
          x:Class="ScratchPad.UserControls.TotalsGridControl" 
          x:Name="TotalsGrid"> 
    
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="*"/> 
         <ColumnDefinition Width="*"/> 
        </Grid.ColumnDefinitions> 
    
    </Grid> 
    

    ここにコードがあります。

    public partial class TotalsGridControl : Grid 
    { 
        public TotalsGridControl() 
        { 
         InitializeComponent(); 
        } 
    
        public static readonly BindableProperty TotalsProperty = 
         BindableProperty.Create(nameof(Totals), typeof(List<TotalItem>), typeof(TotalsGridControl), null, 
          BindingMode.OneWay, null, OnTotalsChanged); 
    
        private static void OnTotalsChanged(BindableObject bindable, object oldvalue, object newvalue) 
        { 
         var control = (TotalsGridControl)bindable; 
         if (control != null) 
         { 
          if (newvalue is List<TotalItem> totals) 
          { 
           var rowNumber = -1; 
           double grandTotal = 0; 
    
           foreach (var totalItem in totals) 
           { 
            grandTotal += totalItem.Value; 
    
            var descLabel = new Label {Text = totalItem.Description}; 
            var valueLabel = new Label { Text = totalItem.Value.ToString("c") }; 
    
            rowNumber++; 
            control.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto}); 
            control.Children.Add(descLabel, 0, rowNumber); 
            control.Children.Add(valueLabel, 1, rowNumber); 
           } 
    
           var grandTotalDescLabel = new Label { Text = "Total" }; 
           var grandTotalValueLabel = new Label { Text = grandTotal.ToString("c") }; 
    
           rowNumber++; 
           control.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); 
           control.Children.Add(grandTotalDescLabel, 0, rowNumber); 
           control.Children.Add(grandTotalValueLabel, 1, rowNumber); 
          } 
         } 
        } 
    
        public List<TotalItem> Totals 
        { 
         get => (List<TotalItem>)GetValue(TotalsProperty); 
         set => SetValue(TotalsProperty, value); 
        } 
    } 
    

    私はTotalItemのリストをユーザーコントロールにバインドできるようにバインド可能なプロパティを使用しました。ここで

    は、ビューモデル

    public List<TotalItem> Totals { get; set; } 
    
    Totals = new List<TotalItem> 
    { 
        new TotalItem {Description = "SubTotal", Value = 99.91}, 
        new TotalItem {Description = "GST", Value = 5.0}, 
        new TotalItem {Description = "PST", Value = 4.9} 
    }; 
    

    のデータであり、ここでXAMLは、ページ内に

    <userControls:TotalsGridControl Totals="{Binding Totals}"/> 
    

    そして、あなたからそれを行うことができ、出力

    enter image description here

    0

    ビューとビューモデルが結合されないように、必要な機能をカプセル化する1つの方法は、ユーザーコントロールを作成することである

    public class ReceiptPageModel : PageModelBase 
    { 
        private Receipt _receipt; 
        public Receipt Receipt 
        { 
         get => _receipt; 
         private set => Set(ref _receipt, value); 
        } 
    
        public override void Init(object initData) 
        { 
         Receipt = (Receipt) initData; 
        } 
    } 
    
    public partial class ReceiptPage : FreshBaseContentPage 
    { 
        public ReceiptPage() 
        { 
         InitializeComponent(); 
         BindingContextChanged += HandlePageModelAdded; 
        } 
    
        private void HandlePageModelAdded(object sender, EventArgs e) 
        { 
         var pageModel = (ReceiptPageModel)BindingContext; 
         if (pageModel.Receipt != null) 
         { 
          AddTaxes(pageModel.Receipt); 
         } 
         else 
         { 
          pageModel.PropertyChanged += (s, args) => 
          { 
           if (args.PropertyName == nameof(pageModel.Receipt)) 
            AddTaxes(pageModel.Receipt); 
          }; 
         } 
        } 
    
        private void AddTaxes(Receipt receipt) 
        { 
         ... 
        } 
    } 
    
    +0

    これはまだページとページのモデルを結合しています。人はもう片方を知るべきではありません。 –

    +0

    @SteveChadbourneこれをどうやって調整しますか?どちらか一方が他方について知っていなくてもこれを達成できる方法はありますか? – Katie

    +0

    私はこれを行うためにユーザーコントロールを使用する方法を示す答えを追加しました。 –

    関連する問題