MasterDetail ListView 和可编辑的 ContentPresenter:怎么了?

MasterDetail ListView and editable ContentPresenter: what is wrong?

我是基于微软官方的示例创建了一个MasterDetail ListViewMasterDetail ListView UWP sample

我已经根据我的情况对其进行了调整,因为我希望用户可以直接编辑来自 ListViewselect 的项目。但是我遇到了一个奇怪的行为:

这是我的应用程序的屏幕截图:

我的ListView的XAML是这样的:

<!-- Master : List of Feedbacks -->
<ListView
    x:Name="MasterListViewFeedbacks"
    Grid.Row="1"
    ItemContainerTransitions="{x:Null}"
    ItemTemplate="{StaticResource MasterListViewFeedbacksItemTemplate}"
    IsItemClickEnabled="True"
    ItemsSource="{Binding CarForm.feedback_comments}"
    SelectedItem="{Binding SelectedFeedback, Mode=TwoWay}">
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.FooterTemplate>
        <DataTemplate>
            <CommandBar Background="White">
                <CommandBar.Content>
                    <StackPanel Orientation="Horizontal">
                        <AppBarButton Icon="Add" Label="Add Feedback"
                                  Command="{Binding AddItemFeedbacksCommand}" />
                        <AppBarButton Icon="Delete" Label="Delete Feedback"
                                  Command="{Binding RemoveItemFeedbacksCommand}" />
                    </StackPanel>
                </CommandBar.Content>
            </CommandBar>
        </DataTemplate>
    </ListView.FooterTemplate>
</ListView>

ListView 的 ItemTemplate 的 XAML 是:

<DataTemplate x:Key="MasterListViewFeedbacksItemTemplate" x:DataType="models:Feedback_Comments">
    <StackPanel Margin="0,11,0,13"
                Orientation="Horizontal">
        <TextBlock Text="{x:Bind creator }" 
                   Style="{ThemeResource BaseTextBlockStyle}" />
        <TextBlock Text=" - " />
        <TextBlock Text="{x:Bind comment_date }"
                   Margin="12,1,0,0" />
    </StackPanel>
</DataTemplate>

Details容器的XAML是这样的:

<!-- Detail : Selected Feedback -->
<ContentPresenter
    x:Name="DetailFeedbackContentPresenter"
    Grid.Column="1"
    Grid.RowSpan="2"
    BorderThickness="1,0,0,0"
    Padding="24,0"
    BorderBrush="{ThemeResource SystemControlForegroundBaseLowBrush}"
    Content="{x:Bind MasterListViewFeedbacks.SelectedItem, Mode=OneWay}">
    <ContentPresenter.ContentTemplate>
        <DataTemplate x:DataType="models:Feedback_Comments">
            <StackPanel Visibility="{Binding FeedbacksCnt, Converter={StaticResource CountToVisibilityConverter}}">

                <TextBox Text="{Binding creator, Mode=TwoWay}" />
                <DatePicker Date="{Binding comment_date, Converter={StaticResource DateTimeToDateTimeOffsetConverter}, Mode=TwoWay}"/>
                <TextBox TextWrapping="Wrap" AcceptsReturn="True" IsSpellCheckEnabled="True"
                         Text="{Binding comment, Mode=TwoWay}" />
            </StackPanel>
        </DataTemplate>
    </ContentPresenter.ContentTemplate>
    <ContentPresenter.ContentTransitions>
        <!-- Empty by default. See MasterListView_ItemClick -->
        <TransitionCollection />
    </ContentPresenter.ContentTransitions>
</ContentPresenter>

CarForm”是我的 ViewModel 的主要对象。每个 CarForm 包含一个列表“Feedback_Comments”。

所以在我的 ViewModel 中,我在添加 新评论 时这样做:

private void AddItemFeedbacks()
{
    FeedbacksCnt++;
    CarForm.feedback_comments.Add(new Feedback_Comments()
    {
        sequence = FeedbacksCnt,
        creator_id = user_id,
        _creator = username,
        comment_date = DateTime.Now
    });
    SelectedFeedback = CarForm.feedback_comments[CarForm.feedback_comments.Count - 1];
}

=> 添加前编辑的Feedback_Comment中所做的修改得到很好的保存

当用户 select 现有 Feedback_Comment 时,我什么都不做:这是由 XAML 直接管理的。

=> 之前编辑的 Feedback_Comment 中对 select 另一个所做的更改未保留

=> 你有什么解释吗?

Text 属性 的 TwoWay 绑定仅在 TextBox 失去焦点时更新。但是,当您 select 列表中的不同项目时,TextBox 的内容不再绑定到原始项目,因此不会更新。

要在每次 Text 内容更改时触发更新,以便立即反映更改,请将 UpdateSourceTrigger 设置为 PropertyChanged:

<TextBox Text="{Binding comment, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

到处触发变化

为确保您的更改在包括列表在内的任何地方都得到反映,您需要做两件事。

首先,您的 feedback_commentsObservableCollection<Feedback_Comments> 类型。这确保添加和删除的项目从 ListView.

中添加和删除

其次,Feedback_Comments class 必须实现 INotifyPropertyChanged 接口。需要此接口让用户界面了解数据绑定对象属性的更改。

实现此接口相当简单,并在 for example on MSDN.

中进行了描述

快速解决方案如下所示:

public class Feedback_Comments : INotifyPropertyChanged
{ 
    // your code

    //INotifyPropertyChanged implementation
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged( [ CallerMemberName ]string propertyName = "" )
    {
        PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
    }
}

现在每个 属性 setter 在设置值后调用 OnPropertyChanged();

private string _comment = "";
public string Comment
{
   get
   {
       return _comment;
   }
   set
   {
       _comment = value;
       OnPropertyChanged();
   }
}

请注意,[CallerMemberName] 属性告诉编译器将参数替换为调用者的名称 - 在本例中为 属性 的名称,这正是您所需要的。

另请注意,在这种情况下您不能使用简单的自动属性(因为您需要调用 OnPropertyChanged 方法。

奖金

最后,作为一个小建议,我看到您正在使用类似 C++ 的命名约定,这不太适合 C# 世界。看看 recommended C# naming conventions 以提高代码可读性:-) .