【问题标题】:UWP ListView x:Bind SelectionMode StackoOverflowExceptionUWP ListView x:Bind SelectionMode StackoOverflowException
【发布时间】:2018-10-21 15:51:24
【问题描述】:

我有一个 ListView,我想更改 ViewModel 中的 SelectionMode。这工作了一半。它的工作原理是我单击一个按钮,并且 SelectionMode 在 Single 和 Multiple 之间变化。但是,如果我在 ListView 中有一个选定的项目并更改为 Multiple,那么我在 MainPage.g.cs 中的此时会得到 StackOverflowException:

public static void Set_Windows_UI_Xaml_Controls_ListViewBase_SelectionMode(global::Windows.UI.Xaml.Controls.ListViewBase obj, global::Windows.UI.Xaml.Controls.ListViewSelectionMode value)
        {
            obj.SelectionMode = value; //<--- here is the error
        }

这是我的列表视图:

<ListView x:Name="MyList" Grid.Row="2" ItemsSource="{x:Bind ViewModel.Threads, Mode=OneWay}" SelectedItem="{x:Bind ViewModel.Selected, Mode=TwoWay}" ShowsScrollingPlaceholders="True" SelectionMode="{x:Bind ViewModel.ListSelectionMode, Mode=OneWay}">
                <interactivity:Interaction.Behaviors>
                    <core:EventTriggerBehavior EventName="SelectionChanged">
                        <core:InvokeCommandAction Command="{x:Bind ViewModel.SelectionChangedCommand}"
                                  InputConverter="{StaticResource SelectionChangedConverter}"
                                  InputConverterParameter="{Binding ElementName=MyList}" />
                    </core:EventTriggerBehavior>
                </interactivity:Interaction.Behaviors>
</ListView>

这里是 ViewModel:

private ListViewSelectionMode _listSelectionMode = ListViewSelectionMode.Single;
    public ListViewSelectionMode ListSelectionMode
    {
        get { return _listSelectionMode; }
        set
        {
            if (_listSelectionMode != value)
            {
                _listSelectionMode = value;
                RaisePropertyChanged();
            }
        }
    }

    private List<object> _selectedThreads = new List<object>();
    public List<object> SelectedThreads
    {
        get { return _selectedThreads; }
        set
        {
            if (value != _selectedThreads)
            {
                _selectedThreads = value;
                RaisePropertyChanged();
            }
        }
    }

    private string _selectedThreadCounter;
    public string SelectedThreadCounter
    {
        get { return _selectedThreadCounter; }
        set
        {
            if (value != _selectedThreadCounter)
            {
                _selectedThreadCounter = value;
                RaisePropertyChanged();
            }
        }
    }

private RelayCommand<IList<object>> _selectionChangedCommand;
    public RelayCommand<IList<object>> SelectionChangedCommand
    {
        get
        {
            if (_selectionChangedCommand == null && ListSelectionMode == ListViewSelectionMode.Multiple)
            {
                _selectionChangedCommand = new RelayCommand<IList<object>>(
                    items =>
                    {
                        SelectedThreads = items.ToList();
                        SelectedThreadCounter = "(" + SelectedThreads.Count + ")";
                    }
                );
            }

            return _selectionChangedCommand;
        }
    }

这里是 SelectionChangedConverter:

public class SelectionChangedConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var listView = parameter as ListView;

        return listView.SelectedItems;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

我希望这些代码足以帮助您找到答案。

更新: 也许我应该在 ViewModel 中添加我的 ItemsSource 看起来像这样:

private IRealmCollection<ThreadRealm> _threads;
    public IRealmCollection<ThreadRealm> Threads
    {
        get { return _threads; }
        set
        {
            if (_threads != value)
            {
                _threads = value;
                RaisePropertyChanged();
            }
        }
    }

它是来自Realm 数据库的 IRealmCollection

【问题讨论】:

  • 我在RaisePropertyChangedSelected 属性中获得了StackoOverflowException
  • 当我将 x:Bind 更改为 Binding 时,RaisePropertyChanged 也会出现异常。但为什么?或者我能做些什么来解决这个问题?

标签: listview mvvm uwp stack-overflow


【解决方案1】:

根据你的描述和代码sn-p,我做了一个代码样例来测试。对我来说效果很好。

请检查以下代码:

<Page.Resources>
    <local:SelectionChangedConverter x:Key="SelectionChangedConverter"></local:SelectionChangedConverter>
</Page.Resources>

<Grid>
    <ListView x:Name="MyList" Grid.Row="2" ItemsSource="{x:Bind ViewModel.Threads,Mode=OneWay}" SelectedItem="{x:Bind ViewModel.Selected,Mode=TwoWay}" ShowsScrollingPlaceholders="True" SelectionMode="{x:Bind ViewModel.ListSelectionMode,Mode=OneWay}">
        <interactivity:Interaction.Behaviors>
            <core:EventTriggerBehavior EventName="SelectionChanged">
                <core:InvokeCommandAction Command="{x:Bind ViewModel.SelectionChangedCommand}"
                              InputConverter="{StaticResource SelectionChangedConverter}"
                              InputConverterParameter="{Binding ElementName=MyList}" />
            </core:EventTriggerBehavior>
        </interactivity:Interaction.Behaviors>
    </ListView>

    <Button Content="switch" Click="Button_Click"></Button>
</Grid>
public sealed partial class MainPage : Page
{
    private ViewModel _viewModel;

    public ViewModel ViewModel { get => _viewModel; set => _viewModel = value; }
    public MainPage()
    {
        this.InitializeComponent();
        ViewModel = new ViewModel();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        ViewModel.ListSelectionMode = MyList.SelectionMode==ListViewSelectionMode.Multiple?ListViewSelectionMode.Single:ListViewSelectionMode.Multiple;
    }
}
public class ViewModel:ViewModelBase
{
    private ListViewSelectionMode _listSelectionMode = ListViewSelectionMode.Single;
    public ListViewSelectionMode ListSelectionMode
    {
        get { return _listSelectionMode; }
        set
        {
            if (_listSelectionMode != value)
            {
                _listSelectionMode = value;
                RaisePropertyChanged();
            }
        }
    }

    private List<object> _selectedThreads = new List<object>();
    public List<object> SelectedThreads
    {
        get { return _selectedThreads; }
        set
        {
            if (value != _selectedThreads)
            {
                _selectedThreads = value;
                RaisePropertyChanged();
            }
        }
    }

    private string _selectedThreadCounter;
    public string SelectedThreadCounter
    {
        get { return _selectedThreadCounter; }
        set
        {
            if (value != _selectedThreadCounter)
            {
                _selectedThreadCounter = value;
                RaisePropertyChanged();
            }
        }
    }

    private RelayCommand<IList<object>> _selectionChangedCommand;
    public RelayCommand<IList<object>> SelectionChangedCommand
    {
        get
        {
            if (_selectionChangedCommand == null && ListSelectionMode == ListViewSelectionMode.Multiple)
            {
                _selectionChangedCommand = new RelayCommand<IList<object>>(
                    items =>
                    {
                        SelectedThreads = items.ToList();
                        SelectedThreadCounter = "(" + SelectedThreads?.Count + ")";
                    }
                );
            }

            return _selectionChangedCommand;
        }
    }


    private ObservableCollection<string> _Threads;
    public ObservableCollection<string> Threads
    {
        get { return _Threads; }
        set
        {
            _Threads = value;
            RaisePropertyChanged();
        }
    }

    private string _Selected;
    public string Selected
    {
        get { return _Selected; }
        set
        {
            if (this._Selected != value)
            {
                _Selected = value;
                RaisePropertyChanged();
            }
        }
    }

    public ViewModel()
    {
        Threads = new ObservableCollection<string>();
        Threads.Add("1");
        Threads.Add("2");
        Threads.Add("3");
    }
}
public class SelectionChangedConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var listView = parameter as ListView;

        return listView.SelectedItems;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

【讨论】:

  • 我检查了它,它崩溃了。您是否也可以在列表中选择一个项目然后切换 SelectionMode?请在我更新的问题中
  • @newone Is it also possible for you to select an item in the list and than switch the SelectionMode? 是的。我的代码示例运行良好。我检查了你更新的代码,它仍然不完整。请上传一个简单的可重现代码示例并在此处发布链接。然后,我将测试您的样本并诊断此问题。
  • 我创建了一个测试项目。您可以从here下载它 重现的步骤在应用程序中谢谢,我希望它有所帮助。
  • @newone 我无法成功构建您的项目。有很多错误。请参阅 Screenshot1Screenshot2。您能否提供一个简单的可重现代码示例?
  • 你试过清理和重建吗?它在我的网站上在不同的 PC 上运行。该项目也是使用“Windows 模板工作室”构建的。
猜你喜欢
  • 2018-09-02
  • 2016-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-24
  • 2017-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多