WPF Listview绑定userControl属性

时间:2013-05-01 09:09:25

标签: c# .net wpf

我是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

的属性

任何人都告诉我为什么它没有绑定?

1 个答案:

答案 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模式开发,因为一旦你开始它就很难停下来,你会想知道你之前做过什么。