ListView中元素的可见性无法正常工作

时间:2016-11-23 13:01:44

标签: c# listview xamarin.forms visibility

我有一个ListView,绑定到ObservableCollection,其模板包含通过用户交互可见/不可见的视图。但是,可见性切换不能按预期工作 - 最初不可见的项目保持不可见,而最初可见的一些项目可以正确地来回切换。我不知道哪里出了问题。

为了追踪问题,我创建了一个极其简化的原始代码版本,并附加了一个绑定(在第2列中)以帮助追踪问题。以下简要介绍了这个简化版本:

ListView的每一行都有一个三列网格。第一列包含两个标签,它们的可见性被切换,即在任何给定时间只能看到一个标签。第二列包含一个标签,其文本与可见的标签相同。第三列包含一个按钮,用于切换第一列中标签的可见性。

在Windows和Android平台上加载页面呈现正常。命中所有命令,并在它们应该调用所有属性的setter。

在UWP上,按下切换按钮后,该行中的所有文本内容都会消失,包括按钮的文本!再次按下切换按钮可使第一列(最初可见)中的文本重新出现,但所有其他文本仍然不可见。

在Win8上,除了按钮文字仍然存在外,它大致相同。

在Android上,切换功能正常,直到选中并删除某个项目。之后,除了最后一项,删除之前的任何项目以及删除之前已切换的任何项目时,第一列在切换显示第二个标签时变为空白,而第二列行为正确。因此,例如,如果我切换Baz,然后删除Bar,则会发生以下情况:Foo,Baz和Kevin的行为与我期望的一样,但Dave将在Dave1和第一列中的任何内容之间切换。

这种行为让我感到非常难过,所以如果有人知道发生了什么,我将非常感激。

这是一个Xamarin.Forms可移植项目,我使用MVVMLightLibs作为ModelBase / RelayCommand,这是我的代码(全部在便携式库中)

查看:

<StackLayout>
  <ListView ItemsSource="{Binding TestList}"
            SelectedItem="{Binding SelectedItem}">
    <ListView.RowHeight>
      <OnPlatform x:TypeArguments="x:Int32" iOS="90" Android="90" WinPhone="100" />
    </ListView.RowHeight>
    <ListView.ItemTemplate>
      <DataTemplate>
        <ViewCell>
          <ContentView Padding="5">
            <Grid HorizontalOptions="FillAndExpand">
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
              </Grid.ColumnDefinitions>
              <Label Text="{Binding Text1}" IsVisible="{Binding Text1Visible}"/>
              <Label Text="{Binding Text2}" IsVisible="{Binding Text2Visible}"/>
              <Label Text="{Binding CurrentText}" Grid.Column="1"/>
              <Button Grid.Column="2"
                      Text="Toggle"
                      Command="{Binding Source={x:Reference MainPage}, Path=BindingContext.ToggleCommand}"
                      CommandParameter="{Binding}"/>
            </Grid>
          </ContentView>
        </ViewCell>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>
  <Button Text="Delete selected" Command="{Binding DeleteCommand}"/>
</StackLayout>

视图模型:

public class MainViewModel : ViewModelBase
{
    public ObservableCollection<MyClass> TestList { get; set; }
    public MyClass SelectedItem { get; set; }
    public RelayCommand<MyClass> ToggleCommand { get; set; }
    public RelayCommand DeleteCommand { get; set; }

    public MainViewModel()
    {
        ToggleCommand = new RelayCommand<MyClass>(ToggleClicked);
        DeleteCommand = new RelayCommand(DeleteSelected);
        TestList = new ObservableCollection<MyClass>();
        TestList.Add(new MyClass { Text1 = "Foo1", Text2 = "Foo2", Text1Visible = true });
        TestList.Add(new MyClass { Text1 = "Bar1", Text2 = "Bar2", Text1Visible = true });
        TestList.Add(new MyClass { Text1 = "Baz1", Text2 = "Baz2", Text1Visible = true });
        TestList.Add(new MyClass { Text1 = "Dave1", Text2 = "Dave2", Text1Visible = true });
        TestList.Add(new MyClass { Text1 = "Kevin1", Text2 = "Kevin2", Text1Visible = true });
    }

    private void DeleteSelected()
    {
        if (SelectedItem != null)
            TestList.Remove(SelectedItem);
    }

    private void ToggleClicked(MyClass myclass)
    {
        myclass.Text2Visible = myclass.Text1Visible;
        myclass.Text1Visible = !myclass.Text1Visible;
    }
}

型号:

public class MyClass : INotifyPropertyChanged
{
    private bool _t1v;
    private bool _t2v;
    private string _text1;
    private string _text2;
    private string _currentText;

    public string Text1
    {
        get { return _text1; }
        set
        {
            _text1 = value;
            RaisePropertyChanged(nameof(Text1));
        }
    }

    public string Text2
    {
        get { return _text2; }
        set
        {
            _text2 = value;
            RaisePropertyChanged(nameof(Text2));
        }
    }

    public string CurrentText
    {
        get { return _currentText; }
        set
        {
            _currentText = value;
            RaisePropertyChanged(nameof(CurrentText));
        }
    }

    public bool Text1Visible
    {
        get { return _t1v; }
        set
        {
            _t1v = value;

            // Set the current text to the one that should be visible
            if (_t1v)
                CurrentText = Text1;
            else
                CurrentText = Text2;

            RaisePropertyChanged(nameof(Text1Visible));
        }
    }

    public bool Text2Visible
    {
        get { return _t2v; }
        set
        {
            _t2v = value;

            // Set the current text to the one that should be visible
            if (_t2v)
                CurrentText = Text2;
            else
                CurrentText = Text1;

            RaisePropertyChanged(nameof(Text2Visible));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

0 个答案:

没有答案