Как добавить элементы в ListBox, не нарушая MVVM - PullRequest
1 голос
/ 20 сентября 2011

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

Должны ли динамические данные просто извлекать элементы в конструкторе пользовательских элементов управления (это кажется неправильным, но будет работать).

Есть мысли?

Платформы не используются, пользовательскиеШаблон MVVM.

Пользовательский элемент управления

<ListBox x:Name="CameraList" Background="#ff4c4c4c" BorderThickness="0" 
 ScrollViewer.CanContentScroll="False" TouchEnter="CameraList_TouchEnter" 
 TouchLeave="CameraList_TouchLeave" 
 ManipulationBoundaryFeedback="CameraList_ManipulationBoundaryFeedback"
 ItemContainerStyle="{DynamicResource ResourceKey=ListBoxItemStyle}" 
 PreviewTouchDown="CameraList_PreviewTouchDown" 
 PreviewTouchMove="CameraList_PreviewTouchMove" 
 PreviewTouchUp="CameraList_PreviewTouchUp" 
 HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <ListBox.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/ResourceLibrary;component/User 
                 Controls/Slider.xaml">
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </ListBox.Resources>
</ListBox>

ViewModel

class CameraListViewModel : WorkspaceViewModel
{
    #region Fields
    private readonly CameraRepository cameraRepository;
    #endregion


    #region Properties
    /// <summary>
    /// Gets and sets the cameras in the system.
    /// </summary>
    public ObservableCollection<CameraViewModel> Cameras { get; private set; }
    #endregion


    #region Constructors
    public CameraListViewModel(CameraRepository cameraRepository)
    {
        if (cameraRepository == null)
        {
            throw new ArgumentNullException("cameraRepository");
        }

        base.DisplayName = "CameraList";

        this.cameraRepository = cameraRepository;

        // Populate the CameraList collection with CameraViewModel.
        this.CreateCameras();
    }
    #endregion


    #region Internal Members
    /// <summary>
    /// Create all the cameras in the system.
    /// </summary>
    private void CreateCameras()
    {
        List<CameraViewModel> all =
            (from cam in cameraRepository.GetCameras()
             select new CameraViewModel(cam, cameraRepository)).ToList();

        foreach (CameraViewModel cvm in all)
        {
            cvm.PropertyChanged += this.OnCameraViewModelPropertyChanged;
        }

        this.Cameras = new ObservableCollection<CameraViewModel>(all);
        this.Cameras.CollectionChanged += this.OnCollectionChanged;
    }
    #endregion


    #region Events
    /// <summary>
    /// Handle changed collections.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null && e.NewItems.Count != 0)
        {
            foreach (CameraViewModel cvm in e.NewItems)
            {
                cvm.PropertyChanged += this.OnCameraViewModelPropertyChanged;
            }
        }

        if (e.OldItems != null && e.OldItems.Count != 0)
        {
            foreach (CameraViewModel cvm in e.OldItems)
            {
                cvm.PropertyChanged -= this.OnCameraViewModelPropertyChanged;
            }
        }
    }

    /// <summary>
    /// Handle property changes.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OnCameraViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        string isSelected = "IsSelected";

        // Make sure that the property name we're referencing is valid.
        // This is a debugging technique, and does not execute in a Release build.
        (sender as CameraViewModel).VerifyPropertyName(isSelected);

        // When a camera is selected or unselected, we must let the system know
        // that properties have changed, so that it will be queried again for a new value.
        if (e.PropertyName == isSelected)
        {
            this.OnPropertyChanged("IsSelected");
        }
    }
    #endregion
}

В настоящее время это работает и отображает списокОднако нужен хороший способ слияния того, что находится в репозитории camera , со списком.

1 Ответ

1 голос
/ 20 сентября 2011

На основе предоставленных вами примеров кода вам необходимо добавить следующее к вашему <ListBox>:

<ListBox ItemsSource="{Binding Path=Cameras}" ...>

Это предполагает, что ваш CameraListViewModel является контекстом данных UserControl или, возможно, контекстом Window. Если нет, вам нужно установить атрибут Source привязки.

Если вам интересно, правильно ли вы закодировали вашу ViewModel (с помощью конструктора, загружающего камеры), я бы сказал, что он выглядит нормально, если он работает.

Я все еще не уверен на 100%, что вы спрашиваете, поэтому я надеюсь, что это ответит на ваш вопрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...