【问题标题】:WPF: Get the selected values ListView BindingWPF:获取选定的值 ListView 绑定
【发布时间】:2014-01-19 15:21:00
【问题描述】:

我在同一个窗口中有 2 个列表视图 第一个加载图像缩略图和图像名称的 listView。在第二个列表视图中,我想更新选定的图像名称/名称并建议用户通过单击按钮删除或查看选定的图像。

我关注了这篇文章(http://www.clear-lines.com/blog/post/Selecting-an-item-in-a-list-with-WPF-and-M-V-VM.aspx),但我无法成功通过绑定获取所选项目。如何从模型中获取选定的图像名称。

代码:

//ImageFile Collection Model
 public class ImageFileCollectionViewModel: INotifyPropertyChanged
    {
        private ObservableCollection<ImageFileViewModel> _allImages;
        private int dataItemsCount;

        public ObservableCollection<ImageFileViewModel> AllImages
        {
            get { return _allImages; }
        }

        public int DataItemsCount
        {
            get
            {
                return dataItemsCount;
            }
            private set
            {
                dataItemsCount = value;
                OnPropertyChanged("DataItemsCount");
            }
        }

        public ImageFileCollectionViewModel()
        {
            this._allImages = new ObservableCollection<ImageFileViewModel>();
            this.DataItemsCount = 0;
        }

        public void AddNewPhotoItem(IImageFile imageFile)
        {
            ImageFileViewModel newImageFileViewModel = new ImageFileViewModel(imageFile);
            this._allImages.Add(newImageFileViewModel);
            this.DataItemsCount++;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public ImageFileViewModel ImageFileName { get; set; }// To get the selected Image name
    }

第一个列表视图:

string destination_dir = System.IO.Directory.GetCurrentDirectory() + @"./4x6";
ImageFileCollectionViewModel ImagesViewModel = new ImageFileCollectionViewModel();
ImageFileControler.CompleteViewList(ImagesViewModel, destination_dir);
ListViewImage.DataContext = ImagesViewModel;

Xaml:

 <ListView  SelectionMode="Multiple"  x:Name="ListViewImage" Width="Auto" 
              ItemsSource="{Binding Path=AllImages}"  Margin="0,20,0,0"
              VirtualizingStackPanel.IsVirtualizing="True"
              VirtualizingStackPanel.VirtualizationMode= "Recycling" Height="333" VerticalAlignment="Top">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <DataTemplate.Resources>
                        <Storyboard x:Key="WaitingTimeline" Timeline.DesiredFrameRate="10">
                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" RepeatBehavior="Forever" 
                            Storyboard.TargetName="WaitingImage" 
                            Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0]
                                                       .(RotateTransform.Angle)">
                                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="-15"/>
                                <SplineDoubleKeyFrame KeyTime="00:00:03" Value="15"/>
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </DataTemplate.Resources>

                    <StackPanel Orientation="Horizontal" Height="100">

                        <Image x:Name="ThumbnailImage" Margin="2" Visibility="Collapsed" Height="120" Width="180" Source="{Binding Path=Thumbnail}" >
                            <Image.BitmapEffect>
                                <DropShadowBitmapEffect ShadowDepth="5" />
                            </Image.BitmapEffect>

                        </Image>
                        <Image x:Name="WaitingImage" Visibility="Visible" Height="20" Width="20" Source="./Hourglass.png">
                            <Image.RenderTransform>
                                <TransformGroup>
                                    <RotateTransform Angle="0" CenterX="10" CenterY="10"/>
                                </TransformGroup>
                            </Image.RenderTransform>

                        </Image>

                        <TextBlock Margin="10,40,0,0" Text="{Binding Path=ShortName}" />
                    </StackPanel>

                    <DataTemplate.Triggers>
                        <DataTrigger Binding="{Binding Path=IsLoaded}" Value="True">
                            <Setter Property="Visibility" TargetName="ThumbnailImage" Value="Visible"/>
                            <Setter Property="Visibility" TargetName="WaitingImage" Value="Collapsed"/>
                        </DataTrigger>

                        <DataTrigger Binding="{Binding Path=IsLoaded}" Value="False">
                            <Setter Property="Visibility" TargetName="WaitingImage" Value="Visible"/>
                            <Setter Property="Visibility" TargetName="ThumbnailImage" Value="Collapsed"/>
                            <DataTrigger.EnterActions>
                                <BeginStoryboard x:Name="WaitingTimeline_BeginStoryboard" Storyboard="{StaticResource WaitingTimeline}"/>
                            </DataTrigger.EnterActions>
                            <DataTrigger.ExitActions>
                                <StopStoryboard BeginStoryboardName="WaitingTimeline_BeginStoryboard"/>
                            </DataTrigger.ExitActions>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </ListView.ItemTemplate>

        </ListView>

第二个 ListView 获取选定的图像名称/名称:

<StackPanel Name="secondLBox" Margin="53,369,10,31" Orientation="Vertical"  >
            <ListBox Height="65" 
                Name="ImageNameListBox" 
                ItemsSource="{Binding AllImages}" 
                DisplayMemberPath="LastName"
               SelectedItem="{Binding Path=ImageFileName}"/>
            <Label Content="Selected Image"/>
            <Label Content="{Binding ImageFileName.FileName}" Visibility="Visible" Height="39"/>

        </StackPanel>

【问题讨论】:

  • 除了 Rohits 的回答之外,如果 ImageViewModel.ImageFileName 应该包含在 ListView 中选择的项目,那么我相信您还应该将 ListView.SelectedItem 绑定到 ImageViewModel.ImageFileName。 (ListView.SelectedItem 默认使用双向绑定)

标签: c# wpf listview


【解决方案1】:

除了 Rohits 的回答之外,如果 ImageViewModel.ImageFileName 应该包含 ListView 中的选定项目,那么您还需要将 ListView.SelectedItem 绑定到 ImageViewModel.ImageFileName。 (ListView.SelectedItem 默认使用双向绑定)

<ListView
    SelectedItem="{Binding Path=ImageFileName}"
    ... all your other stuff from the XAML
/>

ListView.SelectedItem 默认情况下是双向绑定的,因此如果您通过代码隐藏或其他绑定更改 ImageViewModel.ImageFileName,则 ListView 中的选择将更改相应地(假设你也听从了 Rohit 的建议)。


您在 ListBox 中也有一个错误,阻止您查看 ImageViewModel.ImageFileName

请注意,列表框包含 ImageViewModel 类型的项目,因为:

<ListBox
    ItemsSource="{Binding AllImages}"
    ...
/>

现在,任何可能的选定项也将是 ImageViewModel,而不是 ImageViewModel.FileName。因此,您的 ListBox 的设置应与此类似:

<ListBox Height="65" 
    ItemsSource="{Binding AllImages}" 
    SelectedItem="{Binding ImageFileName}"
    DisplayMemberPath="FileName.LastName"
    ...
/>


更新

用力眯起眼睛,代码中发现了另一个可能的问题。

ImageFileCollectionViewModel 应该用作 ListView 的 DataContext ListBox分配给 ListView.DataContext .

若要将 ImageFileCollectionViewModel 也应用为 ListBox 的 DataContext,请明确分配它:

ImageFileCollectionViewModel ImagesViewModel = new ImageFileCollectionViewModel();
ImageFileControler.CompleteViewList(ImagesViewModel, destination_dir);
ListViewImage.DataContext = ImagesViewModel;
ImageNameListBox.DataContext = ImagesViewModel;

或者,如果 ListView 和 ListBox 碰巧共享相同的父/祖先容器 UIElement,则只需在父/祖先容器 UIElement 处设置 DataContext。

【讨论】:

  • 我完全按照你和 Rohits 的做法,但我仍然看不到任何价值。
  • 你可能需要做DisplayMemberPath="(FileName.LastName)"(注意括号)因为点。但我不完全确定你是否需要这样做,因为我目前没有办法验证这一点。
  • 我很确定,你们是对的,但我仍然没有看到价值。因为我想解决这个问题,我可以分享 skydrive 链接吗?
  • 带上它 :) (但请注意,我手头没有 VS,所以我将不得不处理我糟糕的记忆;))
【解决方案2】:

属性 ImageFileName 应在属性内容发生任何更改时引发 PropertyChange event,以便 UI 可以相应地刷新。

声明应该是这样的:

private ImageFileViewModel imageFileName;
public ImageFileViewModel ImageFileName
{
   get
   {
      return imageFileName;
   }
   set
   {
      if(imageFileName != value)
      {
         imageFileName = value;
         OnPropertyChanged("ImageFileName");
      }
   }
}

如果您希望两个 ListBox 同步:

  1. 将第一个 ListBox 的 SelectedItem 与 ImageFileName 绑定。
  2. 将第二个 ListBox 的 SelectedItem 与第一个 ListBox 的 SelectedItem 绑定。

第一个列表框:

<ListBox Name="ListViewImage" 
         SelectedItem="{Binding ImageFileName}"/>

第二个列表框:

<ListBox Name="ImageNameListBox" 
         SelectedItem="{Binding SelectedItem, ElementName=ListViewImage}"/>

【讨论】:

  • 是的,我忘了谢谢。当我单击第一个 LV 时,我仍然看不到第二个列表视图的任何值。
  • @linguini,在你的问题下方查看我的评论(我确实把它作为评论,因为我首先不确定你到底想达到什么目标)
  • @linguini- 请参阅答案中的更新。希望我能正确理解您的问题。
猜你喜欢
  • 2011-02-02
  • 1970-01-01
  • 2014-10-21
  • 2014-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多