将两个 XAML 元素属性绑定到同一个 ViewModel 属性 不起作用

Binding two XAML element properties to the same ViewModel property does not work

问题描述

我用的是Master Details View控件。它有两个属性 Details HeaderSelectedItem。我将两者都绑定到 ViewModel 中的 Selected 属性。目标是根据所选项目更改 DetailsHeader header。问题是只有 SelectedItem 被更新了。文本未出现在 DetailsHeader.

DetailsHeader="{x:Bind ViewModel.Selected, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.Selected, Mode=OneWay}"

如果 link 一个到另一个,它工作正常 - 两者都已更新。

DetailsHeader="{x:Bind masterDetailsView.SelectedItem, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.Selected, Mode=OneWay}"

我在文档中没有发现对上下文中的 属性 只能绑定到 XAML 元素的一个 属性 这一事实的限制。可能是什么问题?

代码

来自 MVVM Light

ViewModelBase 用于更改通知。它的 Set() 方法更新 属性 并引发更改事件。

private SampleVendorModel _selected;
public SampleVendorModel Selected 
{ 
    get => _selected;
    set => Set(ref _selected, value);
}

型号

public class SampleVendorModel
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public string MiddleName { get; set; }

    public string FullName => $"{Surname} {Name} {MiddleName}";
    public string NameWithoutSurname => $"{Name} {MiddleName}";
}

MasterDetailsView

<controls:MasterDetailsView Name="masterDetailsView"
                            MasterHeader="{x:Bind ViewModel.Title}"
                            MasterHeaderTemplate="{StaticResource MasterHeaderTemplate}"  
                            DetailsHeader="{x:Bind masterDetailsView.SelectedItem, Mode=OneWay}"
                            DetailsHeaderTemplate="{StaticResource DetailsHeaderTemplate}"                                   
                            ItemsSource="{x:Bind ViewModel.Items, Mode=OneWay}"
                            SelectedItem="{x:Bind ViewModel.Selected, Mode=OneWay}"
                            ItemTemplate="{StaticResource ItemTemplate}"
                            DetailsTemplate="{StaticResource DetailsTemplate}"                                    
                            BorderBrush="Transparent"
                            BackButtonBehavior="Manual">
</controls:MasterDetailsView>

资源页面

<Page.Resources>
        <Style x:Key="HeaderStyle" TargetType="TextBlock">
            <Setter Property="FontSize" Value="30" />
            <Setter Property="FontWeight" Value="Light" />
            <Setter Property="Margin" Value="0, 10, 0, 10" />
            <Setter Property="TextTrimming" Value="CharacterEllipsis"/>
        </Style>

        <DataTemplate x:Key="MasterHeaderTemplate">
            <TextBlock Text="{Binding}" Style="{StaticResource HeaderStyle}"/>
        </DataTemplate>
        <DataTemplate x:Key="DetailsHeaderTemplate" x:DataType="viewmodels:SampleVendorModel">
            <TextBlock Text="{x:Bind FullName}" Style="{StaticResource HeaderStyle}" />
        </DataTemplate>
        <DataTemplate x:Key="ItemTemplate" x:DataType="viewmodels:SampleVendorModel">
            <Grid Margin="0, 10, 0, 10" RowSpacing="2">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="{x:Bind Surname}" FontWeight="Bold" FontSize="16" TextTrimming="CharacterEllipsis" />
                <TextBlock Grid.Row="1" Text="{x:Bind NameWithoutSurname}" TextTrimming="CharacterEllipsis" />
            </Grid>
        </DataTemplate>
        <DataTemplate x:Key="DetailsTemplate"
                      x:DataType="viewmodels:SampleVendorModel">
            <StackPanel Margin="10">
                <TextBlock Text="{x:Bind Surname}" />
                <TextBlock Text="{x:Bind Name}" />
                <TextBlock Text="{x:Bind MiddleName}" />
            </StackPanel>
        </DataTemplate>
</Page.Resources>

The problem is that only SelectedItem is updated

我委屈了。 MasterDetailsView.SelectedItem 通过代码中的 属性 ViewModel.Selected 更新。如果 UI 导航,ViewModel.Selected 不会改变。因为绑定模式是OneWay。因此,MasterDetailsView.DetailsHeader 不会收到有关所选更改的通知。

为了解决问题,需要将MasterDetailsView.SelectedItem的模式设置为TwoWay

DetailsHeader="{x:Bind ViewModel.Selected, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.Selected, Mode=TwoWay}"