簡體   English   中英

x:嘗試x時綁定StackOverflow:使用TwoWay模式綁定ListView.SelectedItem

[英]x:Bind StackOverflow when trying to x:Bind ListView.SelectedItem using TwoWay mode

我正在嘗試使用新的x:Bind綁定ListView.SelectedItem。 我的代碼:

視圖:

//MainPage.xaml:

<Page
x:Class="BrokenListSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:BrokenListSample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="Beige">
    <Grid.RowDefinitions>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>

    <ListView Grid.Row="0" Background="LawnGreen" 
              ItemsSource="{x:Bind ViewModel.MyItems, Mode=OneWay}"
              SelectedItem="{x:Bind ViewModel.BestItem, Mode=TwoWay}"
              Width="300" Height="300"/>

    <ListView Grid.Row="1" Background="LawnGreen" 
              ItemsSource="{Binding MyItems, Mode=OneWay}"
              SelectedItem="{Binding BestItem, Mode=TwoWay}"
              Width="300" Height="300"/>
</Grid>

代碼隱藏:

//MainPage.xaml.cs:

using Windows.UI.Xaml.Controls;

namespace BrokenListSample
{
    public sealed partial class MainPage : Page
    {
        public MainPageViewModel ViewModel { get; set; }

        public MainPage()
        {
            InitializeComponent();
            DataContextChanged += (s, e) => { ViewModel = DataContext as MainPageViewModel; };
            DataContext = new MainPageViewModel();
        }
    }
}

最后是ViewModel:

//MainPageViewModel.cs:

using System.Collections.ObjectModel;
using System.ComponentModel;

namespace BrokenListSample
{
    public class MainPageViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

        private ObservableCollection<string> _myItems;
        public ObservableCollection<string> MyItems
        {
            get { return _myItems; }
            set { _myItems = value; OnPropertyChanged("MyItems"); }
        }

        private string _bestItem;
        public string BestItem
        {
            get { return _bestItem; }
            set { _bestItem = value; OnPropertyChanged("BestItem"); }
        }

        public MainPageViewModel()
        {
            MyItems = new ObservableCollection<string>() { "One", "Two", "Three", "Four" };
        }
    }
}

如您所見,我的MainPage上有兩個ListView控件。 如果您嘗試運行此代碼,請根據您要檢查的綁定類型對其中一個進行評論。 第二行的ListView使用舊的好Binding,它只是簡單的工作。 這里不足為奇。

驚喜來自於使用新的x:Bind導致StackOverflowException。 使用OneWay模式可以正常工作 - 但只要我點擊其中一個項目,TwoWay就會拋出StackOverflowException ...搞笑......

我的問題很簡單 - “為什么以及如何解決這個問題?”

我面臨同樣的問題。 看一下堆棧跟蹤,我發現我的listview正在修改viewmodel,即修改了onPropertyChanged,修改了listview ...要解決這個問題,你應該修改bound屬性的setter:

public string BestItem
{
  get { return _bestItem; }
  set
  {
    if (_bestItem != value)
    {
      _bestItem = value;
      OnPropertyChanged(nameof(BestItem));
    }
  }
}

ListView的SelectedItem來自Object類型,但您嘗試將其稱為String因此您需要的是一個簡單的轉換器。

我發現除了實現IValueConverter ,你可以使用通用的方法而不做任何事情 - 這在本回答中提到過

public class GenericConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        // no convert to a specific type needed -> the "value" is already an instance of the correct type.
        return value;
    }
}

現在你只需要在x:Bind中引用這個轉換器

<ListView ...
          ItemsSource="{x:Bind ViewModel.MyItems, Mode=OneWay}"
          SelectedItem="{x:Bind ViewModel.BestItem, Mode=TwoWay, 
          Converter={StaticResource GenericConverter}}"
          .../>

在您的App.xaml中(為了使您的所有視圖都可以使用此轉換器):

<Application
x:Class="Namespace.App"
...
xmlns:Converters="using:Namespace.Converters">
<Application.Resources>
    <ResourceDictionary>
        ...
        <Converters:GenericConverter x:Key="GenericConverter"/>
        ...
    </ResourceDictionary>
</Application.Resources>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM