【问题标题】:Xamarin Forms ListView Bindings don't get updatedXamarin Forms ListView 绑定未更新
【发布时间】:2020-03-17 09:20:22
【问题描述】:

我有问题。我用 ViewModel 创建了一个 ListView。在我的 ListView 中,我有一些带有文本的标签,这些标签绑定到 ItemSource 中的对象。现在,当我更改 ObservableCollection 中某个项目的 ViewModel 中的值时,屏幕上没有任何变化!

这是我的 ViewModel:

public class VM_DeviceList : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;


    public ICommand cmdDeleteDevice
    {
        get
        {
            return new Command<int>((x) => DeleteDevice_Handler(x));
        }
    }

    public ICommand cmdTogglePower
    {
        get
        {
            return new Command<int>((x) => TogglePower_Handler(x));
        }
    }


    private ObservableCollection<DisplayedDevice> _knownDeviceList;
    public ObservableCollection<DisplayedDevice> knownDeviceList
    {
        get
        {
            return _knownDeviceList;
        }
        set
        {
            if (_knownDeviceList != value)
            {
                _knownDeviceList = value;

                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("knownDeviceList"));
                }
            }
        }
    }

这是我的 ObservableCollection 类:

public class DisplayedDevice : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

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

    public int Id { get; set; }
    public string Name { get; set; }
    public string State { get; set; }
    public string StateShown { get; set; }
    public string deviceImage { get; set; }
    public string Color { get; set; }
    public string PowerStateColor { get; set; }
    public string DeviceImageColor { get; set; }

    public string DeviceImage
    {
        get
        {
            return deviceImage;
        }

        set
        {
            deviceImage = value;
            OnPropertyChanged();
        }
    }
}

这里是 xaml:

<ListView ItemsSource="{Binding knownDeviceList}" SelectionMode="None" RowHeight="90" ItemTapped="device_Clicked" x:Name="MyListView">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <AbsoluteLayout HeightRequest="70" Margin="20,10,20,10">
                    <StackLayout Opacity="0.3" BackgroundColor="White"
                        AbsoluteLayout.LayoutBounds="0,0,1,1" 
                        AbsoluteLayout.LayoutFlags="All" />
                    <StackLayout AbsoluteLayout.LayoutBounds="0,0,1,1" 
                        AbsoluteLayout.LayoutFlags="All">
                        <Grid RowSpacing="0">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="35" />
                                <RowDefinition Height="35" />
                            </Grid.RowDefinitions>

                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="70" />
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="70" />
                            </Grid.ColumnDefinitions>

                            <Label Grid.Row="0" Grid.Column="1" Text="{Binding Name}" Margin="0,3,0,0"
                        FontAttributes="Bold" FontSize="24" TextColor="White" />
                            <Label Grid.Row="1" Grid.Column="1" Text="{Binding StateShown}" FontSize="18" TextColor="White" />

                            <!-- <Image Source="power" Grid.RowSpan="2" Grid.Column="2" Margin="5" /> -->
                            <controls:IconView x:Name="btnPower" Source="power" Grid.RowSpan="2" Grid.Column="2" Margin="5"
                                            Foreground="{Binding PowerStateColor}">
                                <controls:IconView.GestureRecognizers>
                                    <TapGestureRecognizer Command="{Binding Path=BindingContext.cmdTogglePower, Source={x:Reference MyListView}}" CommandParameter="{Binding Id}" />
                                </controls:IconView.GestureRecognizers>
                            </controls:IconView>
                        </Grid>
                    </StackLayout>
                </AbsoluteLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

现在我期望发生的是,当我单击 IconView 时,我更改了 IconView 颜色和带有 StateShown 绑定的标签。但是当我点击 IconView 时没有任何变化!

我做错了什么?

【问题讨论】:

  • 你的视图模型应该实现 INotifyPropertyChanged docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/…
  • 我已经尝试过了,但我认为我做错了什么。我在 knownDeviceList 中设置了 PropertyChanged,但屏幕上仍然没有任何反应!你能说明我需要如何以正确的方式实施它吗?
  • 请贴出代码来展示你是如何实现它的。
  • 请添加您的DisplayedDevice 类进行查询。您需要对该类中的每个属性调用 OnPropertyChanged,以便 UI 反映其更改。
  • 我更新了上面的代码

标签: c# xamarin xamarin.forms xamarin.android xamarin.ios


【解决方案1】:

OnPropertyChanged 方法调用添加到DisplayedDevice 上的每个属性,以供您希望用户界面注意的对象。

public class DisplayedDevice : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

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

    private string name;
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
            OnPropertyChanged();
        }
    }

    private int id;
    public int Id
    {
        get
        {
            return id;
        }
        set
        {
            Id = value;
            OnPropertyChanged();
        }
    }

    private string state;
    public string State
    {
        get
        {
            return state;
        }
        set
        {
            state = value;
            OnPropertyChanged();
        }
    }
    ......

}

【讨论】:

    【解决方案2】:

    您可以使用 MVVMHelpers NuGet 包并将 ObservableObject 类从 NuGet 直接实现到 DisplayedDevice 类,您需要使用私有变量的引用来制作所有属性。

    public class DisplayedDevice: ObservableObject
        {
    
            string _textField = string.Empty;
            public string TextField
            {
                get => _textField;
                set => SetProperty(ref _textField, value);
            }
            bool _isBarChartVisible = false;
            public bool IsBarChartVisible
            {
                get => _isBarChartVisible;
                set => SetProperty(ref _isBarChartVisible, value);
            }
    }
    }
    

    每个公共属性都应该由相同类型的私有属性支持。这很重要,因此任何属性的任何更改都将使用 INotifyPropertyChanged 反映在 UI 上

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-03
      • 2018-10-16
      • 2017-06-25
      • 2019-04-23
      • 2018-01-03
      • 1970-01-01
      • 2018-01-17
      • 2018-10-13
      相关资源
      最近更新 更多