4

ビューでユーザーが顧客の姓または名を変更できるようにする小さなテスト WPF MVVM アプリケーションがあり、フルネームが自動的に変更されるため、M から MV から V への通信が行われます。 、すべてが完全に分離されており、これまでのところ非常に良好です。

しかし、MVVM パターンを使用して大規模なアプリケーションを構築するためにこれを拡張する方法を検討していると、デカップリングが障害になることがわかります。

  • 検証メッセージをどのように行うのですか。たとえば、LastName セッターのモデルに戻って、50 文字を超える名前が設定されないようにするコードを追加した場合、名前が多すぎるというメッセージを表示するようにビューにメッセージを送信するにはどうすればよいですか?長いです?

  • 複雑なアプリケーションでは、一度に画面に数十のビューがある場合がありますが、MVVM では、データと動作を提供するために各ビューに割り当てられた ViewModel が 1 つだけであることを理解しています。たとえば、上記の検証の例で、顧客モデルに戻って、特定の「MessageAreaView」に「姓には50文字しか含まれていない可能性があります」というメッセージを表示するよう通知したい場合、スタックをどのように通信するかその特定のビューに?

CustomerHeaderView.xaml (ビュー):

<UserControl x:Class="TestMvvm444.Views.CustomerHeaderView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <StackPanel HorizontalAlignment="Left">
            <ItemsControl ItemsSource="{Binding Path=Customers}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <StackPanel Orientation="Horizontal">
                                <TextBox
                                Text="{Binding Path=FirstName, Mode=TwoWay}" 
                                Width="100" 
                                Margin="3 5 3 5"/>
                                <TextBox 
                                Text="{Binding Path=LastName, Mode=TwoWay}" 
                                Width="100"
                                Margin="0 5 3 5"/>
                                <TextBlock 
                                Text="{Binding Path=FullName, Mode=OneWay}" 
                                Margin="0 5 3 5"/>
                            </StackPanel>
                        </StackPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </StackPanel>
    </Grid>
</UserControl>

Customer.cs (モデル):

using System.ComponentModel;

namespace TestMvvm444.Model
{
    class Customer : INotifyPropertyChanged
    {

        public int ID { get; set; }
        public int NumberOfContracts { get; set; }

        private string firstName;
        private string lastName;

        public string FirstName
        {
            get { return firstName; }
            set
            {
                if (firstName != value)
                {
                    firstName = value;
                    RaisePropertyChanged("FirstName");
                    RaisePropertyChanged("FullName");

                }
            }
        }

        public string LastName
        {
            get { return lastName; }
            set
            {
                if (lastName != value)
                {
                    lastName = value;
                    RaisePropertyChanged("LastName");
                    RaisePropertyChanged("FullName");
                }
            }
        }

        public string FullName
        {
            get { return firstName + " " + lastName; }
        }



        #region PropertChanged Block
        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }
        #endregion
    }
}
4

3 に答える 3

6

検証のために、ビュー モデルに を実装させIDataErrorInfoます。ビュー間の通信に関しては、UI サービス (たとえば、ビュー モデルが UI のどこかに表示されるメッセージを提供できるようにするメッセージ サービス) を作成することを恐れないでください。または、ビュー モデル間に厳密な関係がある場合 (たとえば、あるビュー モデルが別のビュー モデルを所有している場合)、所有しているビュー モデルは子ビュー モデルへの参照を保持できます。

于 2009-04-03T09:04:24.823 に答える
2

検証メッセージを追加する非常に簡単な方法は、バインディングを使用することです。

検証メッセージを表示するかどうかを定義する通知可能なプロパティをビュー モデルに追加します。

private Boolean _itemValidatorDisplayed;
public Boolean ItemValidatorDisplayed
{
    get { return _itemValidatorDisplayed; }
    set
    {
        _itemValidatorDisplayed= value;
        _OnPropertyChanged("ItemValidatorDisplayed");
    }
}

bool を可視性に変換するコンバーター クラスを追加します。

using System;
using System.Windows;

namespace xxx
{
    public class BoolToVisibilityConverter : IValueConverter
    {
        public bool Negate { get; set; }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            bool val = System.Convert.ToBoolean(value);
            if (!Negate)
            {
                return val ? Visibility.Visible : Visibility.Collapsed;
            }
            else
            {
                return val ? Visibility.Collapsed : Visibility.Visible;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

ビューからプロパティにバインドし、コンバーターを適用します。

    <UserControl x:Class="ViewClass"
    ...
    >
        <UserControl.Resources>
            <contract:BoolToVisibilityConverter Negate="False"
                                                x:Key="BoolToVisibilityConverter" />
        </UserControl.Resources>

...

<TextBlock Visibility="{Binding Converter={StaticResource BoolToVisibilityConverter}, Path=ItemValidatorDisplayed}" />

...

</UserControl>

ビューのデータ コンテキストとして ViewModel を設定する必要があります。

namespace xxx
{
    public partial class ViewClass: UserControl
    {
        public ViewClass()
        {
            InitializeComponent();

            this.DataContext = new ViewClass_ViewModel();
        }
}
}

ビンゴ - この ViewModel / プロパティをサブスクライブするすべてのビューに、完全に機能する検証がプッシュされます。

于 2009-04-06T11:23:59.703 に答える
0

SL3 のソース オブジェクト コレクションに検証をバインドすることもできます :-)

于 2009-07-07T12:04:17.477 に答える