XAML 当选择更改时,CollectionView中的SelectedItem不会自动刷新

nmpmafwu  于 2023-09-28  发布在  其他
关注(0)|答案(2)|浏览(114)

我不知道为什么当我在CollectionView上更改SelectedItem时,ToolbarItem文本没有自动刷新。我对xamarin,c#或一般编码没有太多经验,但我无法想象这是一件很大的事情。
我试图调试问题与一些停止在“AktuellesProjekt”属性,但它没有帮助那么多。我只是不知道该怎么补救。
<ToolbarItem Text="{Binding AktuellesProjekt.Name}" Order="Primary"/>

视图模型:

public class DashViewModel : BaseViewModel
{
    //Name
    public const string ViewName = "DashPage";
    
    //Konstruktur
    public DashViewModel()
    {
        //Titel
        Title = "Dash";

        //Commands intialisieren
        LadeProjekte();
    }

    //Commands

    //Fields
    private ObservableCollection<ProjektModel> _projekte = new ObservableCollection<ProjektModel>();
    private ProjektModel _aktuellesProjekt = new ProjektModel();

    //Properties
    public ObservableCollection<ProjektModel> Projekte
    {
        get { return _projekte; }
        set
        {
            if (value == _projekte)
                return;

            OnPropertyChanged(nameof(Projekte));
        }
    }

    public ProjektModel AktuellesProjekt
    {
        get { return _aktuellesProjekt; }
        set
        {
            {
                if (value == _aktuellesProjekt)
                    return;

                OnPropertyChanged(nameof(AktuellesProjekt));
            }
        }
    }

    //Methoden
    public void LadeProjekte()
    {
        for (int i = 2020; i <= 2040; i++)
        {
            var projekt = new ProjektModel
            {
                Name = i,
                BestandGesamt = 12000.00 + (i - 2020) * 1000,
                LetzteAktualisierung = "31.12." + i.ToString(),
                AnzahlEintraege = 76 - (i - 2020) * 10
            };

            Projekte.Add(projekt);
            AktuellesProjekt = Projekte[0];
        }
    }
}

检视:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             Title="{Binding Title}"
             BackgroundColor="{StaticResource NormalBackgroundColor}"
             xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core" 
             
             xmlns:fa="clr-namespace:DXApp3.Resources"
             xmlns:dxcv="http://schemas.devexpress.com/xamarin/2014/forms/collectionview"
             xmlns:viewmodels="clr-namespace:DXApp3.ViewModels"
             xmlns:models="clr-namespace:DXApp3.Models"
             
             ios:Page.UseSafeArea="true"
             x:Class="DXApp3.Views.DashPage">

    <ContentPage.ToolbarItems>
        <ToolbarItem Text="{Binding AktuellesProjekt.Name}" Order="Primary"/>
    </ContentPage.ToolbarItems>
    
    <ContentPage.BindingContext>
        <viewmodels:DashViewModel/>
    </ContentPage.BindingContext>

    <ContentPage.Content>

        <Grid>

            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>

            <ScrollView Grid.Row="0">
                <dxcv:DXCollectionView ItemsSource="{Binding Projekte}"
                                       SelectedItem="{Binding AktuellesProjekt}"
                                       SelectionMode="Single">
                    
                    <dxcv:DXCollectionView.ItemTemplate>
                        <DataTemplate>
                            <Grid Padding="10,10,10,10">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>

                                <Grid.RowDefinitions>
                                    <RowDefinition Height="*"/>
                                    <RowDefinition Height="*"/>
                                </Grid.RowDefinitions>

                                <Label Grid.Row="0" Grid.Column="0" 
                                       Text="{Binding Name, StringFormat='Finanzen {0}'}"
                                       TextColor="Black"
                                       HorizontalTextAlignment="Start"
                                       VerticalTextAlignment="Center"
                                       FontSize="18"/>
                            </Grid>
                        </DataTemplate>                        
                    </dxcv:DXCollectionView.ItemTemplate>
                    
                </dxcv:DXCollectionView>
            </ScrollView>

            <Button Grid.Row="0" BorderColor="Transparent" BorderWidth="1" FontAttributes="Bold" BackgroundColor="#1968B3" CornerRadius="25" TextColor="White" 
                    HorizontalOptions="End" VerticalOptions="End" WidthRequest="50" HeightRequest="50" Margin="0,0,20,22">
                <Button.ImageSource>
                    <FontImageSource FontFamily="fa-solid" Size="Medium" Glyph="{x:Static fa:FaSolid.Plus}" />
                </Button.ImageSource>
            </Button>
        </Grid>

    </ContentPage.Content>

</ContentPage>
tag5nh1u

tag5nh1u1#

问题#1:缺少备份字段的更新

首先,您实际上并没有在这里更新后台字段:

public ObservableCollection<ProjektModel> Projekte
{
    get { return _projekte; }
    set
    {
        if (value == _projekte)
            return;

        OnPropertyChanged(nameof(Projekte));
    }
}

public ProjektModel AktuellesProjekt
{
    get { return _aktuellesProjekt; }
    set
    {
        {
            if (value == _aktuellesProjekt)
                return;

            OnPropertyChanged(nameof(AktuellesProjekt));
        }
    }
}

您需要将backing字段设置为value

public ObservableCollection<ProjektModel> Projekte
{
    get { return _projekte; }
    set
    {
        if (value == _projekte)
            return;

        _projekte = value;

        OnPropertyChanged(nameof(Projekte));
    }
}

public ProjektModel AktuellesProjekt
{
    get { return _aktuellesProjekt; }
    set
    {
        if (value == _aktuellesProjekt)
            return;

        _aktuellesProjekt = value;

        OnPropertyChanged(nameof(AktuellesProjekt));
    }
}

问题#2:工具栏项未更新

现在AktuellesProjekt得到了正确的更新(或者至少应该更新),根据您的评论,我做了一个快速搜索,发现了issue #14886。似乎ToolbarItem上的绑定不能正常工作。

解决方案

一种解决方法是在代码后面订阅ViewModel的PropertyChanged事件,然后手动更新ToolbarItemText属性:

public class DashPage : ContentPage
{
    private DashViewModel _viewModel;

    public DashPage()
    {
        InitializeComponent();
    }

    protected override void OnBindingContextChanged()
    {
        if(BindingContext is DashViewModel viewModel)
        {
            if(_viewModel != null)
            {
                _viewModel.PropertyChanged -= OnViewModelPropertyChanged;
            }

            _viewModel = viewModel;

            _viewModel.PropertyChanged += OnViewModelPropertyChanged;
        }
    }

    private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if(e.PropertyName == nameof(_viewModel.AktuellesProjekt))
        {
            TitleItem.Text = _viewModel.AktuellesProjekt.Name;
        }
    }
}

为此,您还需要为工具栏项提供x:Name属性:

<ContentPage.ToolbarItems>
    <ToolbarItem x:Name="TitleItem" Text="{Binding AktuellesProjekt.Name}" Order="Primary"/>
</ContentPage.ToolbarItems>

简化

如果不在XAML中设置BindingContext,而是在代码隐藏中设置,则可以稍微简化。
从你的XAML中删除:

<ContentPage.BindingContext>
    <viewmodels:DashViewModel/>
</ContentPage.BindingContext>

然后,您的代码隐藏可能如下所示:

public class DashPage : ContentPage
{
    private readonly DashViewModel _viewModel;

    public DashPage()
    {
        InitializeComponent();
        BindingContext = _viewModel = new DashViewModel();
        _viewModel.PropertyChanged += OnViewModelPropertyChanged;
    }

    private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if(e.PropertyName == nameof(_viewModel.AktuellesProjekt))
        {
            TitleItem.Text = _viewModel.AktuellesProjekt.Name;
        }
    }
}
xuo3flqw

xuo3flqw2#

这里有一个简单的方法来实现这一点。
首先,您需要使用方法SelectionChanged创建CollectionView。

<ContentPage.ToolbarItems>
        <ToolbarItem x:Name="Toolbaritem"/>
    </ContentPage.ToolbarItems>

    <CollectionView ItemsSource="{Binding Data}"
                    SelectionMode="Single"
                    SelectionChanged="OnCollectionViewSelectionChanged">
        ...
    </CollectionView>

第二,你可以使用下面的代码实现SelectionChanged方法。然后,您需要从CollectionView获取数据并将数据传递到ToolbarItem .

private void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
       var entity = (Entity)e.Item;
       Toolbaritem.Text = entity.Name;
    }

每次按下CollectionviewItem后,此方法都会将数据传递给ToolbarItem。

相关问题