0

(ファイル)エクスプローラーのようなアイコン表示を実装したい。商品には日付とラベルがあります。

ユーザーはラベルを編集できる必要があります。

  • アイテムを一つ選べ
  • ラベルをクリック
  • ラベルの TextBlock は、編集用の TextBox に置き換えられます

編集を終了する方法 (情報のみ):

  • TextBox の外側の任意の場所をクリックします
  • Enter キーボード キーを押します (ICommand を実装して?)

最初に、コードで TextBlock と TextBox の可視性を設定しようとしましたが、それは「正しい」方法ではないことがわかりました。(Data)Triggers を使用してアイテムのラベルを編集することは可能でしょうか?

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

参照: 依存関係プロパティの値の優先順位

パート II: ListView とファイル エクスプローラーのような動作

4

2 に答える 2

1

MediaItem はINotifyPropertyChangedを実装する必要があり、バインドする必要があるその各プロパティは、バインドが正しく機能するために RaisePropertyChanged を呼び出す必要があります。あなたの場合、 IsEditing の Binding には、値が変更されたことを知る方法がありません。

于 2013-01-28T10:55:04.163 に答える
0

IsEditing プロパティをバインドするには、変更されたときに WPF に通知する必要があります。

次に、で実装する必要がありINotifyPropertyChangedますMediaItem。(または依存関係プロパティを追加します)

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 に答える