【发布时间】:2011-09-19 20:17:47
【问题描述】:
我已经为 WPF 应用程序设置了一个 MVVM 设计模式,我正在尝试考虑将列表框项附加到列表框的最佳方法,并假设这应该在视图模型中完成。如果是这样的话,那我就卡住了。我的主窗口包含一个内容控件,该控件将适当的视图作为用户控件拉入。我假设我必须将列表框的 itemssource 绑定到视图模型中的属性,但我不确定如何尝试此操作,因为我无权访问相机视图中的列表框。
动态数据是否应该只拉入用户控件构造函数中的项目(这似乎是错误的,但会起作用)。
有什么想法吗?
没有使用框架,自定义 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 中的内容合并到列表框的好方法。
【问题讨论】:
-
你是对的,这应该在视图模型中完成,但你没有提供足够的信息来回答你的问题。有很多方法可以做到这一点,但这在很大程度上取决于您如何设置系统,是否使用任何 MVVM 框架等。
-
我在上面添加了一些逻辑来帮助澄清。
-
MVVM 是关于 Context...DataContext,在这种情况下。假设您的父视图将您的 ViewModel 作为 DataContext,那么任何子控件(甚至是 UserControls)也将具有相同的 DataContext(除非您专门将其设置为不同的东西)。您应该能够简单地将您的 ListBox ItemsSource 绑定到要显示的字符串集合。
-
关于 EtherDragon 的响应,所以如果我的主窗口里面有用户控件,我应该能够在用户控件中检索 CameraList。那么我应该能够将相机列表中的项目源绑定到主窗口视图模型或相机列表视图模型中的项目源?