如何在不违反MVVM的情况下将项目附加到ListBox

时间:2011-09-19 20:17:48

标签: c# wpf mvvm

我已经为WPF应用程序设置了一个MVVM设计模式,我正在考虑将列表框项目附加到列表框的最佳方法,并假设这应该在viewmodel中完成。如果是这样的话,那我就被困住了。我的主窗口包含一个contentcontrol,它将适当的视图作为usercontrol引入。我假设我必须将列表框的itemssource绑定到viewmodel中的属性,但我不知道如何尝试这个,因为我无法访问摄像机视图中的列表框。

动态数据是否只是拉入用户控件构造函数中的项目(这看起来不对,但可行)。

有什么想法吗?

没有使用框架,自定义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>

视图模型

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
}

目前,这可以显示列表框,但是需要一种很好的方法将 camerarepository 中的内容合并到列表框中。

1 个答案:

答案 0 :(得分:1)

根据您提供的代码示例,您需要将以下内容添加到<ListBox>

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

这假定您的CameraListViewModelUserControl的数据上下文,或者Window的上下文。如果没有,则需要设置绑定的Source属性。

如果你想知道你是否已正确编码ViewModel(使用构造函数加载摄像头),我会说假设它工作正常。

我仍然不能100%肯定你在问什么,所以我希望这能回答你的问题。