首页 > 解决方案 > Xamarin 找到将我的对象作为数据上下文的视图单元

问题描述

我有一个通过 dataBinding 填充的 ListView,它的 viewCells 通过 DataTemplateSelector 进行模板化。

我的 ListView 看起来像这样:

<ListView x:Name="PuzzlesContainer"
          ItemsSource="{x:Static gameBrain:GameItems.Puzzles}"
          RowHeight="167"
          ItemTemplate="{StaticResource PuzzleDataTemplateSelector}"/>

然后在某个时候,我将在一个拼图中进行修改,该拼图需要用在其 viewCell 上的画布中绘制的线条来表示(来自 DataTemplate)

如何访问将我的拼图作为 DataContext 的 ViewCell 以便能够手动更新 Canvas ?

标签: listviewxamarin

解决方案


在列表中创建一个从 ViewCell 派生的自定义控件。在 xaml 中您将拥有一个模板,在代码隐藏中您将设置值而不将 xaml 绑定到数据。它会更新得更快。从理论上讲,您不需要模板选择器,因为在代码隐藏中您现在可以用您的单元格做所有事情。你的细胞等级:

            private INotifyPropertyChanged _oldBindingContext;

//this normally fires when you set your list ItemsSource
            protected override void OnBindingContextChanged()
            {
                if (_oldBindingContext != null)
                {
                    _oldBindingContext.PropertyChanged -= OnBindingContextPropertyChanged;
                }

                if (BindingContext != null)
                {
                    INotifyPropertyChanged ctx = null;
                    try
                    {
                        ctx = (INotifyPropertyChanged)BindingContext;
                    }
                    catch
                    {
                        base.OnBindingContextChanged();
                        return;
                    }
                    ctx.PropertyChanged += OnBindingContextPropertyChanged;
                }
                _oldBindingContext = (INotifyPropertyChanged)BindingContext;
                OnCellBindingContextChanged();
                base.OnBindingContextChanged();
            }

            public virtual void OnCellBindingContextChanged()
            {
            if (BindingContext == null) return;

            //update your xaml here.

            var model = (MyItemCLass)BindingContext;
            MyXamlTextBox.Text = model.Title;


            }

    //you are left with the challenge to call dispose manually when your page destroys. 
    //im calling this from my custom list for every cell when page pops up
            public void Dispose()
            {
                if (BindingContext != null)
                {
                    INotifyPropertyChanged ctx = null;
                    try
                    {
                        ctx = (INotifyPropertyChanged)BindingContext;
                        ctx.PropertyChanged -= OnBindingContextPropertyChanged;
                    }
                    catch
                    {
                    }
                }           
            }

            //and this is what your question is about:
            //when a single property of your model changes we land here to react
            private void OnBindingContextPropertyChanged(object sender, PropertyChangedEventArgs e)
            {                        
                if (e== null || BindingContext==null) return;
    var = PropertyName = e?.PropertyName;
    //todo more checks

                var propertyInfo = BindingContext.GetType().GetProperty(propertyName);
                if (propertyInfo == null) return;

                if (propertyName == "IsFavorite")
                {
                    UpdateFav((MySupaItem)BindingContext);
                }

    }

推荐阅读