0

我想实现(文件)资源管理器,如图标显示。这些项目有日期和标签。

用户应该能够编辑标签:

  • 选择一个项目
  • 点击标签
  • Label 的 TextBlock 替换为 TextBox 进行编辑

如何结束编辑(仅供参考):

  • 单击文本框外的任意位置
  • 按 Enter 键盘键(通过实施 ICommand?)

第一次我尝试在代码中设置 TextBlock 和 TextBox 的可见性,发现这不是“正确”的做法。也许可以使用(数据)触发器编辑项目的标签?

我可以跟踪 OnClickLabelBlock 并设置 selectedMedia.IsEditing = true; 但它不会触发触发器。知道为什么 MediaItem.IsEditing 属性值更改会通知 DataTrigger 吗?与执行顺序或优先级机制有关吗?

我将选择引导我找到“最佳”架构来解决它的答案。

谢谢。

XAML:

<Window x:Class="WPFComponents.DailyImages"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Model="clr-namespace:WPFComponents.Model"
    Title="Media Items" Height="300" Width="300">

<ListView x:Name="_mediaItemList" ItemsSource="{Binding MediaItems}"
          ScrollViewer.HorizontalScrollBarVisibility="Disabled" SelectionMode="Multiple">
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="IsSelected" Value="{Binding IsSelected}" />
        </Style>
    </ListView.ItemContainerStyle>

    <ListView.ItemTemplate>
        <DataTemplate DataType="Model:MediaItem">

            <Grid Width="80" Margin="4">
                <Grid.RowDefinitions>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                </Grid.RowDefinitions>
                <Image HorizontalAlignment="Center" Stretch="Uniform" Source="{Binding Path=IconPath}" Width="70" />

                <StackPanel Grid.Row="2">
                    <TextBlock Text="{Binding Path=Date}" TextWrapping="Wrap" />

                    <TextBlock x:Name="_labelTextBlock" Text="{Binding Path=Label}" TextWrapping="Wrap"
                               PreviewMouseLeftButtonDown="OnClickLabelBlock">
                    </TextBlock>

                    <TextBox x:Name="_labelTextBox" Text="{Binding Path=Label}" Visibility="Collapsed"
                             TextWrapping="WrapWithOverflow" TextAlignment="Center">
                    </TextBox>
                </StackPanel>
            </Grid>

            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding IsEditing}" Value="True">
                    <Setter TargetName="_labelTextBlock" Property="Visibility" Value="Collapsed" />
                    <Setter TargetName="_labelTextBox" Property="Visibility" Value="Visible" />
                </DataTrigger>
            </DataTemplate.Triggers>

        </DataTemplate>
    </ListView.ItemTemplate>

    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel IsItemsHost="True" VerticalAlignment="Top" />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>

</ListView>

来源:

public partial class DailyImages
{
    public DailyImages()
    {
        InitializeComponent();

        ViewModel.DailyImages dailyImages = new ViewModel.DailyImages();
        // DailyImages has ObservableCollection<MediaItem> MediaItems property
        _mediaItemList.DataContext = dailyImages;
    }

    private void OnClickLabelBlock(object sender, MouseButtonEventArgs e)
    {
        TextBlock notes = sender as TextBlock;

        if (notes == null)
            return;

        MediaItem selectedMedia = notes.DataContext as MediaItem;

        if (selectedMedia == null)
        {
            // TODO: Throw exception
            return;
        }
        _mediaItemList.SelectedItems.Clear();
        selectedMedia.IsSelected = true;
        selectedMedia.IsEditing = true;
    }

public class MediaItem
{
    public MediaItem()
    {
        IsEditing = false;
        IsSelected = false;
    }

    public DateTime Date { get; set; }
    public string Label { get; set; }
    public string IconPath { get; set; }
    public bool IsEditing { get; set; }
    public bool IsSelected { get; set; }
}

参考: 依赖属性值优先级

第二部分:ListView & File Explorer Like 行为

4

2 回答 2

1

MediaItem 必须实现INotifyPropertyChanged并且它的每个必须绑定的属性都必须调用 RaisePropertyChanged 才能使绑定正常工作。在您的情况下, IsEditing 上的 Binding 无法知道该值已更改。

于 2013-01-28T10:55:04.163 回答
0

若要绑定您的 IsEditing 属性,必须在 WPF 被修改时通知它。

然后你必须INotifyPropertyChangedMediaItem. (或添加依赖属性)

public class MediaItem : INotifyPropertyChanged
{
    public MediaItem()
    {
        IsEditing = false;
        IsSelected = false;
    }

    // Use the same pattern for Date, Label & IconPath if these value may change after the MediaItem instance has been added to the collection MediaItems.
    public DateTime Date { get; set; }
    public string Label { get; set; }
    public string IconPath { get; set; }

    private bool isSelected;
    public bool IsSelected
    {
        get { return isSelected; }
        set
        {
            if (isSelected != value)
            {
                isSelected = value;
                OnPropertyChanged("IsSelected");
            }
        }
    }

    private bool isEditing;
    public bool IsEditing
    {
        get { return isEditing; }
        set
        {
            if (isEditing != value)
            {
                isEditing = value;
                OnPropertyChanged("IsEditing");
            }
        }
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}

否则,您的代码是正确的。

于 2013-01-28T10:55:46.870 回答