Различать экземпляры пользовательских элементов управления с помощью mvvm-light - PullRequest
0 голосов
/ 10 августа 2010

У меня есть два экземпляра пользовательского элемента управления File Browser, элемент управления - это просто кнопка и текстовое поле, но мне нужны два экземпляра, подумайте о утилите diff.Как только пользователь выбрал файл для каждого элемента управления, я хочу включить кнопку, которая будет выполнять действие над обоими файлами.

Проблема, с которой я сталкиваюсь, заключается в том, как различать экземпляры элементов управления по порядку.определить, что оба файла были выбраны.Я думаю, я хотел бы, чтобы у моего DoSumthinViewModel были только строковые свойства, которые выполняет FileChooserViewModel.

Сначала у меня был один ViewModelLocator со свойством, которое возвращало новый экземпляр FileChooserVM при доступе, но это простоЯ не был прав, и я не мог различить случаи.Затем я пошел по пути отдельного локатора для FileChooser, но понял, что каждый элемент управления будет снова общаться с одним и тем же экземпляром локатора и, следовательно, с тем же FileChooserViewModel.

Итак, что будет хорошим методом для работы сотдельные экземпляры одного и того же ViewModel?

Спасибо,

Держатель Шейна

1 Ответ

0 голосов
/ 10 августа 2010

Ваш DoSomethingViewModel может иметь два свойства типа FileChooserViewModel, к которым привязаны ваши элементы управления, а затем проверить их строковые свойства на предмет значения.

Упрощенная версия вашей FileChooserViewModel может быть ...

public class FileChooserViewModel : ViewModelBase
{
    public const string FilePathPropertyName = "FilePath";
    private string _filePath;
    public string FilePath
    {
        get { return _filePath; }
        set
        {
            if (_filePath == value) return;
            _filePath = value;
            RaisePropertyChanged(FilePathPropertyName);
            Messenger.Default.Send(new NotificationMessage("FilePath Updated"));
        }
    }
}

И ваша DoSomethingViewModel может выглядеть так ...

public class DoSomethingViewModel : ViewModelBase
{
    public DoSomethingViewModel()
    {
        Messenger.Default.Register<NotificationMessage>(this, NotificationMessageReceived);
    }

    public const string FileChooser1PropertyName = "FileChooser1";
    private FileChooserViewModel _fileChooser1 = new FileChooserViewModel();
    public FileChooserViewModel FileChooser1
    {
        get { return _fileChooser1; }
        set
        {
            if (_fileChooser1 == value) return;
            _fileChooser1 = value;
            RaisePropertyChanged(FileChooser1PropertyName);
        }
    }

    public const string FileChooser2PropertyName = "FileChooser2";
    private FileChooserViewModel _fileChooser2 = new FileChooserViewModel();
    public FileChooserViewModel FileChooser2
    {
        get { return _fileChooser2; }
        set
        {
            if (_fileChooser2 == value) return;
            _fileChooser2 = value;
            RaisePropertyChanged(FileChooser2PropertyName);
        }
    }

    public const string BothFilesChosenPropertyName = "BothFilesChosen";
    public bool BothFilesChosen
    {
        get
        {
            var result = false;
            if (FileChooser1 != null && FileChooser2 != null)
                result = !string.IsNullOrWhiteSpace(FileChooser1.FilePath)
                      && !string.IsNullOrWhiteSpace(FileChooser2.FilePath);
            return result;
        }
    }

    private void NotificationMessageReceived(NotificationMessage msg)
    {
        if (msg.Sender is FileChooserViewModel)
            RaisePropertyChanged(BothFilesChosenPropertyName);
    }
}

Метод NotificationMessageReceived вызывается с NotificationMessage, отправляемым из установщика свойства FilePath FileChooserViewModel, и он, в свою очередь, вызывает событие измененного свойства в свойстве BothFilesChosen.

<UserControl x:Class="DoSomethingProject.Views.DoSomethingView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:views="clr-namespace:DoSomethingProject.Views"
             DataContext="{Binding DoSomethingViewModel, Source={StaticResource Locator}}">
    <StackPanel>
        <views:FileChooser DataContext="{Binding Path=FileChooser1}" />
        <views:FileChooser DataContext="{Binding Path=FileChooser2}" />
        <Button IsEnabled="{Binding Path=BothFilesChosen}" />
    </StackPanel>
</UserControl>

Еще один способ сделать это - обработать событие PropertyChanged для каждого свойства FileChooserViewModel, но я предпочитаю использовать обмен сообщениями, потому что обработка событий означает, что вам нужно убедиться, что вы не обрабатываете события, и это может привести к беспорядку, приводящему к проблемам с памятью когда пропущены события.

...