我是WPF
的新人。我有Listview
,我希望显示的内容超过usercontrol
。
我使用过ItemTemplate。
像这样的Listview:
<ListView HorizontalAlignment="Stretch" Margin="0,40,0,0" Name="listView1" VerticalAlignment="Stretch"
ItemTemplate="{StaticResource DriveUserControlDataTemplate}" >
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="{Binding (FrameworkElement.ActualWidth), RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"
ItemWidth="{Binding (ListView.View).ItemWidth, RelativeSource={RelativeSource AncestorType=ListView}}"
MinWidth="{Binding ItemWidth, RelativeSource={RelativeSource Self}}"
ItemHeight="{Binding (ListView.View).ItemHeight, RelativeSource={RelativeSource AncestorType=ListView}}" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
<DataTemplate x:Key="DriveUserControlDataTemplate" >
<StackPanel Margin="10">
<c:DriveUserControl Drive="{Binding Name}" EventAdd="DriveUserControlAdd_Click">
</c:DriveUserControl >
</StackPanel>
</DataTemplate>
我希望通过以下代码绑定usercontrol:
listView1.ItemsSource = DriveInfo.GetDrives()
.Where(item => item.IsReady && item.DriveType == DriveType.Removable)
.ToList();
类DriveInfo
具有名为Name
任何人都告诉我为什么它没有绑定?
答案 0 :(得分:1)
WPF的主要实现方法是MVVM(模型视图ViewModel),而不是代码隐藏。您需要做的是实现MVVM开发模式。我可以建议您先阅读有关MVVM的许多在线文章之一,http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
然而,我不会只是指向一个链接,而是尽力尝试回答你的问题。
创建一个类并将其命名为MainWindowViewModel并实现INotifyPropertyChanged接口。完成此操作后,实现PropertyChanged事件。在这一点上,当我的属性发生变化时,我喜欢欺骗并给自己写一个帮助方法来为我举起这个事件。
public class MainWindowViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private void raisePropertyChanged(string propertyName) {
if (PropertyChanged != null) PropretyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
所以在这一点上你应该有如上所示的东西。这是ViewModel。
下一步是创建要向用户界面View公开的属性。在您的情况下,您要列出计算机上可用的驱动器。所以我们需要创建一个字符串值的ObservableCollection,如下所示。
private ObservableCollection<string> _drives = new ObservableCollection<string>();
public ObservableCollection<string> Drives {
get { return _drives; }
set {
_drives = value;
this.raisePropertyChanged("Drives");
}
}
到目前为止我可以吗?所以现在我们有了一个视图模型和一个空字符串值列表。真棒啊?下一步是填充字符串“Drives”列表,这样我们就可以在类中编写一个简单的Init方法。
public void Init() {
this.Drives = new ObservableCollection<string>(DriveInfo.GetDrives()
.Where(item => item.IsReady && item.DriveType == DriveType.Removable)
.ToList());
}
让我们暂时保留代码,现在我们将注意力转向View(您的UI)。在UI中,您需要定义ViewModel类所在的命名空间。这是在窗口中放入xaml的第一个元素。
xmlns:vms="clr-namespace:applicationNameSpace;assembly=applicationAssemblyName"
不要忘记将applicationNameSpace和applicationAssemblyName替换为正确的值。
接下来,我们在窗口的资源中声明ViewModel类。
<Window.Resources>
<vms:MainWindowViewModel x:Key="mainWindowVms"/>
</Window.Resources>
最后但并非最不重要的是为您的窗口和后面的代码创建一个Loaded事件,是的,我说代码落后,请输入以下代码。
MainWindowViewModel mainWindowVms = Resources["mainWindowVms"] as MainWindowViewModel;
mainWindowVms.Init();
所以这只留下最后一件事,就是回答你关于“它为什么没有绑定?”的问题。好吧,因为ItemsSource是一个需要由ViewModel中的属性绑定的属性。换句话说,它使用INotifyPropertyChanged接口来通知UI线程已对其绑定的对象进行了更改。绑定代码背后的类型失败了WPF的目的。因此,为了获得绑定,您只需在xaml中指定绑定。
<ListView ItemsSource="{Binding Source={StaticResource mainWindowVms}, Path=Drives"/>
通过这种方式,您可以让您的视图模型担心列表的状态和数量,并且您的UI只会执行它所说的内容。
所以你有它。这很重要,特别是如果你是WPF新手,你读过MVVM模式开发,因为一旦你开始它就很难停下来,你会想知道你之前做过什么。