0

我是新来的WPF。我有Listview,而且我想展示的不仅仅是usercontrol它。

我使用了项目模板。

像这样的列表视图:

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

我想通过这段代码绑定用户控件:

 listView1.ItemsSource = DriveInfo.GetDrives()
                .Where(item => item.IsReady && item.DriveType == DriveType.Removable)
                .ToList();

DriveInfo具有名为的属性Name

谁能告诉我为什么它没有绑定?

4

1 回答 1

1

WPF 的主要实现方法是 MVVM(模型视图视图模型),而不是代码隐藏。您需要做的是实现 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));
  }
}

因此,此时您应该拥有如上图所示的内容。这是视图模型。

下一步是创建要向用户界面(视图)公开的属性。在您的情况下,您想列出计算机上可用的驱动器。所以我们需要创建一个字符串值的 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());
}

让我们暂时不理会代码,现在我们将注意力转向视图(您的 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.xml 中指定绑定即可。

<ListView ItemsSource="{Binding Source={StaticResource mainWindowVms}, Path=Drives"/>

这样,您的视图模型就会担心列表的状态和数量,而您的 UI 只会按照它的指示进行操作。

所以你有它。这很重要,特别是如果您是 WPF 新手,请阅读 MVVM 模式开发,因为一旦开始就很难停下来,您会想知道在此之前您做过什么。

于 2013-05-01T13:07:23.203 回答