开发者

How do I append items to a ListBox without violating MVVM

开发者 https://www.devze.com 2023-04-06 03:45 出处:网络
I have set up a MVVM design pattern to the WPF application and I\'m trying to think of the best way to append listbox items to a listbox and am assuming this should be done in the viewmodel. If this i

I have set up a MVVM design pattern to the WPF application and I'm trying to think of the best way to append listbox items to a listbox and am assuming this should be done in the viewmodel. If this is the case, then i'm stuck. My mainwindow holds a contentcontrol that pulls in the appropriate view as a usercontrol. I'm assuming I would have to bind the itemssource of the listbox to a property in the viewmodel but I'm not sure how to attempt this as I don't have access to the listbox in the camera view.

Should the dynamic data just pull in the items in the user controls constuctor (this seems wrong but would work).

Any thoughts?

No frameworks are used, custom MVVM pattern.

User Control

<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<CameraViewMode开发者_运维技巧l> 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
}

Currently this works and will display the listbox, however need a good way of merging what is in the camerarepository into the listbox.


Based on the code samples you provided you need to add the following to your <ListBox>:

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

This assumes that your CameraListViewModel is the UserControl's data context, or perhaps the Window's context. If not, you will need to set the Source attribute of the binding.

If you're wondering if you've coded your ViewModel properly (with the constructor loading the cameras), I would say that it looks fine assuming it works.

I'm still not 100% sure what you're asking, so I hope this answers your question.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号