WPF:获取选定值ListView绑定

时间:2014-01-19 15:21:01

标签: c# wpf listview

我在同一个窗口中有2个listviews 第一个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
    }

First ListView:

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>

2 个答案:

答案 0 :(得分:1)

属性ImageFileName应该对属性内容的任何更改提出PropertyChange event,以便UI可以相应地进行刷新。

宣言应该是这样的:

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

如果您希望两个ListBox同步:

  1. 将SelectedItem绑定到第一个带有ImageFileName的ListBox。
  2. 使用第一个ListBox的SelectedItem将SelectedItem绑定到第二个ListBox。
  3. First ListBox:

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

    第二个ListBox:

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

答案 1 :(得分: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 ListBox的DataContext,分配给 ListView.DataContext

要将 ImageFileCollectionViewModel 也作为 ListBox 的DataContext应用,请明确指定:

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

或者只是将DataContext设置在父/祖先容器UIElement上,如果ListView和ListBox碰巧共享同一个父/祖先。