0

(Caliburn.Microを使用して)MVVMを使い始めましたが、これを正しく行っているかどうかわからない問題が発生しました。MediaCacherConfigデータをjson形式で保存するテキストファイルを表すモデルがあります。モデルには、2つの文字列リストと1つの文字列が含まれています。

私が苦労しているのは、ビューモデル、特にAddNewFolder()メソッドを正しく設定する方法です。正しいイベントを発生させているかどうか、およびビューモデルの表現が正しいかどうかはわかりません。単純なプロパティにバインドする方法はわかりますが、アイテム(文字列)が追加されるたびにまったく新しいコレクションを作成しているため、コレクションへのバインドは少し頭がおかしいようです。

さらに、まったく新しいモデルをロードするときは、意味をなさないすべてのプロパティに対してNotifyPropertyChanged()メソッドを実行する必要があります。

どんなガイダンスでも大歓迎です。

public class MediaCacherConfig : IConfig
{

    public string DatabaseFileName { get; set; }

    public ICollection<string> FoldersToScan { get; set; }

    public ICollection<string> ExtensionsToIgnore { get; set; }

}

私はビューモデルを持っていますMediaCacherConfigViewModel

    public class MediaCacherConfigViewModel : PropertyChangedBase
{

    private MediaCacherConfig Model { get; set; }

    public string DatabaseFileName
    {
        get { return Model.DatabaseFileName; }
        set
        {
            Model.DatabaseFileName = value;
            NotifyOfPropertyChange(() => DatabaseFileName);
        }
    }

    public BindableCollection<string> FoldersToScan
    {
        get
        {
            return new BindableCollection<string>(Model.FoldersToScan);
        }
        set
        {
            Model.FoldersToScan = value;
            NotifyOfPropertyChange(() => FoldersToScan);
        }
    }

    public BindableCollection<string> ExtensionsToIgnore
    {
        get
        {
            return new BindableCollection<string>(Model.ExtensionsToIgnore);
        }
        set
        {
            Model.ExtensionsToIgnore = value;
            NotifyOfPropertyChange(() => ExtensionsToIgnore);
        }
    }

    /* Constructor */
    public MediaCacherConfigViewModel()
    {
        LoadSampleConfig();
    }

    /* Methods */
    public void LoadSampleConfig()
    {

        MediaCacherConfig c = new MediaCacherConfig();

        string sampleDatabaseFileName = "testing.config";

        List<string> sampleFoldersToScan = new List<string>();
        sampleFoldersToScan.Add("A");
        sampleFoldersToScan.Add("B");
        sampleFoldersToScan.Add("C");

        List<string> sampleExtensionsToIgnore = new List<string>();
        sampleExtensionsToIgnore.Add("txt");
        sampleExtensionsToIgnore.Add("mov");
        sampleExtensionsToIgnore.Add("db");
        sampleExtensionsToIgnore.Add("dat");

        c.DatabaseFileName = sampleDatabaseFileName;
        c.FoldersToScan = sampleFoldersToScan;
        c.ExtensionsToIgnore = sampleExtensionsToIgnore;

        Model = c;

        NotifyOfPropertyChange(() => DatabaseFileName);
        NotifyOfPropertyChange(() => FoldersToScan);
        NotifyOfPropertyChange(() => ExtensionsToIgnore);


    }

    public void AddNewFolder()
    {
        Model.FoldersToScan.Add("new one added");
        NotifyOfPropertyChange(() => FoldersToScan);

    }

    public void SaveConfig()
    {
        ConfigTools.Configure(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Cacher", "Config"));

        ConfigTools.SaveConfig(Model,"sampleconfig.txt");              
    }

    public void LoadConfig()
    {
        ConfigTools.Configure(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Cacher", "Config"));

        MediaCacherConfig m = ConfigTools.LoadConfig<MediaCacherConfig>("sampleconfig.txt") as MediaCacherConfig;
        Model = m;


        NotifyOfPropertyChange(() => DatabaseFileName);
        NotifyOfPropertyChange(() => FoldersToScan);
        NotifyOfPropertyChange(() => ExtensionsToIgnore);

    }
}

そして、これが私の見解です:

<UserControl x:Class="MediaCacher.Views.MediaCacherConfigView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="413" Width="300">
<Grid MinWidth="300" MinHeight="300" Background="LightBlue" Margin="0,0,0,0">
    <Grid.RowDefinitions>
        <RowDefinition Height="409*"/>
        <RowDefinition Height="4*"/>
    </Grid.RowDefinitions>
    <TextBox x:Name="DatabaseFileName" TextWrapping="Wrap" Margin="10,64,10,0" HorizontalAlignment="Center" Width="280" Height="42" VerticalAlignment="Top"/>
    <ListBox x:Name="FoldersToScan" HorizontalAlignment="Left" Height="145" Margin="10,111,0,0" VerticalAlignment="Top" Width="280"/>
    <ListBox x:Name="ExtensionsToIgnore" HorizontalAlignment="Left" Height="145" Margin="10,261,0,0" VerticalAlignment="Top" Width="280"/>
    <Button x:Name="AddNewFolder" Content="Add" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="87" Height="49"/>
    <Button x:Name="LoadConfig" Content="Load" HorizontalAlignment="Left" Margin="102,10,0,0" VerticalAlignment="Top" Width="96" Height="49"/>
    <Button x:Name="SaveConfig" Content="Save" HorizontalAlignment="Left" Margin="203,10,0,0" VerticalAlignment="Top" Width="87" Height="49"/>
</Grid>

4

1 に答える 1

2

まず、ここでは毎回新しいコレクションを返しているので、明らかに何も持続しません。

 public BindableCollection<string> FoldersToScan
    {
        get
        {
            return new BindableCollection<string>(Model.FoldersToScan);
        }
        set
        {
            Model.FoldersToScan = value;
            NotifyOfPropertyChange(() => FoldersToScan);
        }
    }

次に、AddFolderメソッドはViewModelに属している必要があります。既存のコレクションに文字列を追加すると、それがBindingCollectionであるという事実により、新しいアイテムが追加されたというイベントがビューに自動的に発生します。


これが私がやる方法です。これは明らかにデモンストレーション目的の例です。必要なものをすべて追加してください。あなたは理想的には合格したいと思っており、私はそれをすべて書き出す時間がないので、私はEventArgs実装していないことに注意してください。INotifyPorpertyChangedまた、私は使用してObservableCollectionいますが、あなたはあなたを使用することができますBindableCollection

この例のポイントは、ViewModel->モデル通信を管理する方法を示すことです。技術的に言えば、View->ViewModelはCommandPatternを介して通信する必要があります。

public class YourViewModel
    {
        private readonly YourModel model;
        private ObservableCollection<string> foldersToScan = new ObservableCollection<string>();
        public ObservableCollection<string> FoldersToScan
        {
            get { return this.foldersToScan; }
        }

        public YourViewModel(YourModel model)
        {
            this.model = model;
            this.model.OnItemAdded += item => this.foldersToScan.Add(item);
        }

        public void AddFolder(string addFolder) //gets called from view
        {
            this.model.AddFolder(addFolder); //could be ICommand using Command Pattern
        }
    }

    public class YourModel
    {
        private readonly List<string> foldersToScan;
        public IEnumerable<string>  FoldersToScan
        {
            get { return this.foldersToScan; }
        }


        public event Action<string> OnItemAdded; 

        public YourModel()
        {
            this.foldersToScan = new List<string>();
        }

        public void AddFolder(string folder)
        {
            this.foldersToScan.Add(folder);
            this.RaiseItemAdded(folder);
        }

        void RaiseItemAdded(string folder)
        {
            Action<string> handler = OnItemAdded;
            if (handler != null) handler(folder);
        }
    }
于 2012-12-07T18:51:38.000 に答える