【问题标题】:How can I bind to something other than a property in ListView?如何绑定到 ListView 中的属性以外的东西?
【发布时间】:2021-02-02 15:18:08
【问题描述】:

我正在开发一个抽认卡应用。我有这两种模型:Deck 和 Card。

甲板:

 public class Deck
    {
        public int Id { get; set; }
        public string Name { get; set; }
     }

卡片:

 public class Card
    {
        public int Id { get; set; }
        public string Front { get; set; }
        public string Back { get; set; }
     }

在我的用户的 HomeViewModel 中,他们会在列表视图中看到他们的牌组列表。在每一行中,他们都会看到牌组的名称、牌组的数量,然后是一个按钮,可以选择研究、编辑或删除每个牌组。

我的问题是关于显示牌组的牌数。现在,我的 HomeViewModel 看起来像这样:

public class HomeViewModel : BaseViewModel
    {
        private int _count;
        public int Count
        {
            get
            {
                return _count;
            }
            set
            {
                _count = Count;
                OnPropertyChanged("Count");
            }
        }
        private readonly IDeckManager _deckManager;
        public CreateDeckViewModel _createDeckViewModel { get; set; }
        public ObservableCollection<Deck> Decks { get; set; }

        public HomeViewModel(CreateDeckViewModel createDeckViewModel, IAuthenticator authenticator, IDeckManager deckManager)
        {
            //Decks = all of the current users decks
            _deckManager = deckManager;

            Decks = new ObservableCollection<Deck> 
                      (_deckManager.getDecks(authenticator.CurrentUser.Id).Result);
            
            //the result comes in, but I must be binding incorrectly
            foreach (Deck deck in Decks)
            {
                  Count = _deckManager.getCardCount(deck.Id).Result;
            }
            _createDeckViewModel = createDeckViewModel;
        }
    }

我的 IDeckManager 与我的数据库进行交互并返回牌组中的牌数。

My View 有一个 ItemsSource 的 Deck。对于 Name 列,我只是使用

Text="{Binding Path=Name}"

但是由于 Deck 没有关于它拥有的卡片数量的属性,我不确定要绑定到什么。这是我目前的计数:

Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type viewModels:HomeViewModel}}, 
                    Path=Stuff, UpdateSourceTrigger=PropertyChanged, FallbackValue=500}"

我还尝试在 foreach 循环和转换器中使用当前 Deck 的 Id 调用 getCardCount 方法,但是转换器构造函数不能接受参数,因此我的 IDeckManager 的实例,我无法获取 foreach循环工作。

这里还有其他选择吗?提前致谢。

【问题讨论】:

    标签: c# wpf xaml mvvm binding


    【解决方案1】:

    由于您将卡片组作为 DataContext,并且您可以通过 FindAncestor 绑定到 HomeViewModel,您可以使用 IMultiValueConverter 并将两者都发送给它,进行所需的计算并返回卡片的数量。

    public class DeckToCountConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            int count = 0;
            if(values.Length == 2 && values[0] is Deck && values[1] is HomeViewModel)
            {
                Deck deck =  values[0] as Deck;
                HomeViewModel vm = values[1] as HomeViewModel;
                count = vm.GetCountByDeckId(deck.Id);
            }
    
            return count;
        }
    
     
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    由于您的 IDeckManager 是私有的,您要么需要将其公开,要么编写一个 GetCountByDeckId 方法(我在这里所做的),要么有某种按 id 计数的字典(代码中的计数重新分配给计数,所以它总是有它计算的最后一副牌的计数)。

    public class HomeViewModel : INotifyPropertyChanged
    {
        ...
        public int GetCountByDeckId(int deckId)
        {
            return _deckManager.getCardCount(deckId).Result;
        }
    }
    

    如果您需要对 ListView 进行多重绑定的参考: Multibinding within a list view

    【讨论】:

    • 感谢您的帮助。我不知道我可以将(的实例?)我的 HomeViewModel 发送到转换器。现在我正在努力使用 XAML 语法,我不确定路径应该是什么,因为它必须是一个绑定,尽管 ID 工作正常。现在,发送 HomeViewModel 我有:&lt;Binding Path="???" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type viewModels:HomeViewModel}}" /&gt;
    • 由于我无法编辑我的最后一条评论,我会说我将绑定更改为:&lt;Binding Mode="OneWay" Source="{RelativeSource FindAncestor, AncestorType={x:Type viewModels:HomeViewModel}}" /&gt; 并且我更接近,我实际上在 values[1] 处获得了一个值,但它是一个RelativeSource 对象,所以我目前正试图弄清楚我的Source 是否以某种方式出错。当我使用 RelativeSource 而不是 Source 时,我在转换器中得到一个空的 PropertySource 对象。
    • 假设 HomeViewModel 是 window\usercontrol 的 dataContext,&lt;Binding RelativeSource="{RelativeSource AncestorType=local:MyWindow}" Path="DataContext" /&gt; 应该对你有好处..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-21
    相关资源
    最近更新 更多