2

ここに画像の説明を入力

アイテムを選択してそのラベルを編集できるようにしたい:

  • アイテムを一つ選べ
  • アイテムが強調表示されます
  • そのラベルをクリックします
  • ラベルの TextBlock は TextBox に置き換えられます
  • ラベルを変更する
  • 一度に編集できるアイテムは 1 つだけです

編集を終了します。

  1. アイテムのアイコンをクリックします:
    • TextBox は TextBlock に置き換えられます
    • 項目が強調表示されたまま
  2. 別の項目がクリックされます:
    • TextBox は TextBlock に置き換えられます
    • 編集された項目が選択されていません
    • クリックしたアイテムが選択され、強調表示されます
  3. ウィンドウの他の領域がクリックされます。
    • TextBox は TextBlock に置き換えられます
    • 編集された項目が強調表示されたまま

動作は、Windows エクスプローラーとほぼ同じです。

ほとんどの要件を満たすことができました。それでもランダムな結果が得られます。たとえば、最初の起動時に、ラベルを直接クリックして編集できます。アイテム自体は強調表示されません。これは開始時にのみ発生します。

また、スクロールバーを使用しても、リスト項目からフォーカスが外れません。これにより、複数のアイテムを同時に編集できます。

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"
          MouseLeftButtonDown="OnClickMediaList" IsSynchronizedWithCurrentItem="True">

    <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.Style>
                            <Style TargetType="TextBlock">
                                <Setter Property="Visibility" Value="Visible" />
                            </Style>
                        </TextBlock.Style>
                    </TextBlock>

                    <TextBox x:Name="_labelTextBox" Text="{Binding Path=Label}" Visibility="Collapsed"
                             TextWrapping="WrapWithOverflow" TextAlignment="Center"
                             LostFocus="OnTextLostFocus">
                    </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();
        _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) return;

        // Multiple items might be selected
        // Clear all selected items
        _mediaItemList.SelectedItems.Clear();

        // Reselect
        selectedMedia.IsSelected = true;
        selectedMedia.IsEditing = true;

        Mouse.Capture(this, CaptureMode.SubTree);
    }

    private void OnTextLostFocus(object sender, RoutedEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        if (textBox == null) return;

        MediaItem mediaItem = textBox.DataContext as MediaItem;
        if (mediaItem == null)
            return;

        // End the label editing
        mediaItem.IsEditing = false;

        ReleaseMouseCapture();
    }

    private void OnClickMediaList(object sender, MouseButtonEventArgs e)
    {
        // End the label editing
        foreach (MediaItem mediaItem in _mediaItemList.Items)
            mediaItem.IsEditing = false;

        ReleaseMouseCapture();
    }
}

MediaItem.cs

public class MediaItem : INotifyPropertyChanged
{
    private bool _isEditing;
    private bool _isSelected;
    private string _label;

    public MediaItem()
    {
        IsEditing = false;
        _isSelected = false;
    }

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

    public string Label
    {
        get { return _label; }
        set
        {
            _label = value;
            OnPropertyChanged("Label");
        }
    }

    public DateTime Date { get; set; }
    public string IconPath { get; set; }

    public bool IsSelected
    {
        get { return _isSelected; }
        set
        {
            _isSelected = value;
            OnPropertyChanged("IsSelected");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

DailyImages.cs

public class DailyImages
{
    private ObservableCollection<MediaItem> _mediaItems;

    public DailyImages()
    {
        _mediaItems = new ObservableCollection<MediaItem>();

        _mediaItems.Add(new MediaItem {Label = "Image 1", IconPath = "Resources/Icon1.png"});
        _mediaItems.Add(new MediaItem {Label = "Image 2", IconPath = "Resources/Icon2.png"});
        _mediaItems.Add(new MediaItem {Label = "Image 3", IconPath = "Resources/Icon3.png"});
        _mediaItems.Add(new MediaItem {Label = "Image 4", IconPath = "Resources/Icon4.png"});
        _mediaItems.Add(new MediaItem {Label = "Image 5", IconPath = "Resources/Icon5.jpg"});
        _mediaItems.Add(new MediaItem {Label = "Image 6", IconPath = "Resources/Icon6.png"});
        _mediaItems.Add(new MediaItem {Label = "Image 7", IconPath = "Resources/Icon7.png"});
        _mediaItems.Add(new MediaItem {Label = "Image 8", IconPath = "Resources/Icon8.png"});
        _mediaItems.Add(new MediaItem {Label = "Image 9", IconPath = "Resources/Icon9.png"});
    }

    public ObservableCollection<MediaItem> MediaItems
    {
        get { return _mediaItems; }
        set { _mediaItems = value; }
    }
}

長い投稿を読んでくれてありがとう。

ここStackOverflowで多くの回答を検索して読みましたが、どれも私にとって素晴らしいものではありませんでした。

例えば:

4

2 に答える 2

0

リストビューでscrolleventをキャプチャし、要素のフォーカスを明示的に削除することをお勧めします。

    ScrollViewer scrollViewer = GetVisualChild<ScrollViewer>(mTreeView);
    scrollViewer.ScrollChanged += new ScrollChangedEventHandler(scrollViewer.....

ハンドラー内でフォーカスを削除します。

要素からフォーカスを移動するためのこのstackoverflowページを見てください WPF:プログラムでTextBoxからフォーカスを削除する方法

于 2013-01-29T17:50:02.453 に答える
0

異なる状態で IsReadonly プロパティを切り替える方が良いのでしょうか? その後、可視性を切り替える必要がなくなります。また、この場合はテンプレートを置き換えたほうがよいでしょう。

于 2013-01-29T18:46:31.393 に答える