簡體   English   中英

Xamarin Forms 中的綁定數據問題

[英]Problem with binding data in Xamarin Forms

我是 Xamarin Forms (XF) 的新手。 當我嘗試綁定數據時,我遇到了一個我不明白的問題。 如果我通過接口(如選擇器)更新任何屬性,則PropertyChanged存在。 但是如果我通過代碼更新任何屬性, PropertyChanged不存在。 我嘗試通過分配PropertyChanged = delegate {}來修復它, PropertyChanged存在但handler(this, new PropertyChangedEventArgs(propertyName)); 無法在我的界面上更新屬性值。 這是我的例子:

  • 在 MainPage.xaml 中:
<Picker Grid.Row="1" Title="Select a component" ItemsSource="{Binding ComponentTree.Children}" ItemDisplayBinding="{Binding Name}" SelectedItem="{Binding SelectedGrandFatherComponent}" />
<Picker Grid.Row="2" Title="Select a component" ItemsSource="{Binding SelectedGrandFatherComponent.Children}" ItemDisplayBinding="{Binding Name}" SelectedItem="{Binding SelectedFatherComponent}" />
<Picker Grid.Row="3" x:Name="SelectedComponentPicker" Title="Select a component" ItemsSource="{Binding SelectedFatherComponent.Children}" ItemDisplayBinding="{Binding Name}" SelectedItem="{Binding SelectedComponent}" />
<ScrollView Grid.Row="4">
  <interfaces:SimpleTreeView BindingContext="{Binding SelectedComponent}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</ScrollView>
<Label Text="{Binding SelectedComponentStructure}"></Label>
  • 在 TreeCardView.xaml 中:
<Button Grid.Column="1" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Command="{Binding Appear}"  BackgroundColor="Transparent" CommandParameter="{Binding Name}" />
  • 在 TreeNode.cs 中(如樹中每個節點的 controller (TreeCardView.xaml)):
public TreeNode()
{
  Appear = new Command<string>((x) => ShowUp(x));
}
public static void ShowUp(string name)
{
  StructureDesignViewModel instance = new StructureDesignViewModel();
  StructureDesignViewModel.HandleSelectedComponent delegateIns = new StructureDesignViewModel.HandleSelectedComponent(instance.SetSelectedComponent);
  delegateIns(name);
}
  • 在 StructureDesignViewModel.cs(如 MainPage.xaml 的控制器)中:
public class StructureDesignViewModel : ObservableObject, INotifyPropertyChanged
    {
        private static readonly StructureDesignViewModel instance = new StructureDesignViewModel();

        public static StructureDesignViewModel Instance
        {
            get
            {
                return instance;
            }
        }
        public static IList<Component> Components
        {
            get
            {
                return ComponentData.Components;
            }
        }
        TreeNode selectedGrandFatherComponent;
        TreeNode selectedFatherComponent;
        TreeNode selectedComponent;
        string selectedComponentStructure;

        public TreeNode BaseTree
        {
            get; set;
        }

        public TreeNode ComponentTree
        {
            get; set;
        }


        void GrowUp(TreeNode node, List<Component> components)
        {
            int len = components.Count;
            for (int i = 0; i < len; i++)
            {
                var currentNode = node.Children.Add(new TreeNode { Name = components[i].Name, Status = components[i].Status, IsExpanded = false, Modals = components[i].Modals });
                GrowUp((TreeNode)currentNode, components[i].Childs);
            }
        }
        public StructureDesignViewModel()
        {
            ComponentTree = new SimpleTreeView().ViewModel.MyTree;
            ComponentTree = new TreeNode { Name = "Component Root", Status = 0, IsExpanded = true };
            GrowUp(ComponentTree, (List<Component>)Components);
        }
        public TreeNode SelectedGrandFatherComponent
        {
            get { return selectedGrandFatherComponent; }
            set
            {
                if (selectedGrandFatherComponent != value)
                {
                    selectedGrandFatherComponent = value;
                    OnPropertyChanged();
                }
            }
        }

        public TreeNode SelectedFatherComponent
        {
            get
            {
                if (selectedGrandFatherComponent?.Children.Count > 0)
                {
                    selectedFatherComponent = (HMIStudio.Shared.Interfaces.TreeNode)selectedGrandFatherComponent.Children[0];
                }
                return selectedFatherComponent;
            }
            set
            {
                if (selectedFatherComponent != value)
                {
                    selectedFatherComponent = value;
                    OnPropertyChanged();
                }
            }
        }

        public TreeNode SelectedComponent
        {
            get
            {
                if (selectedFatherComponent?.Children.Count > 0)
                {
                    selectedComponent = (HMIStudio.Shared.Interfaces.TreeNode)selectedFatherComponent.Children[0];
                }
                return selectedComponent;
            }
            set
            {
                if (selectedComponent != value)
                {
                    selectedComponent = value;
                    OnPropertyChanged();
                }
            }
        }

        public string SelectedComponentStructure
        {
            get
            {
                return selectedComponentStructure;
            }
            set
            {
                if (selectedComponentStructure != value)
                {
                    Set("SelectedComponentStructure", ref selectedComponentStructure, value);
                }
            }
        }
        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
                if (propertyName == "SelectedGrandFatherComponent")
                {
                    OnPropertyChanged(nameof(SelectedFatherComponent));
                }
                else if (propertyName == "SelectedFatherComponent")
                {
                    OnPropertyChanged(nameof(SelectedComponent));
                }
            }
        }
        public delegate void HandleSelectedComponent(string Name);
        public void SetSelectedComponent(string name)
        {
            Console.WriteLine("Showing selected component {0}", name);
            SelectedComponentStructure = name;
        }
    }
  • 在 ObservableObject.cs 中:
public class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        protected virtual void Set<T>(string propertyName, ref T backingField, T newValue, Action beforeChange = null, Action afterChange = null)
        {
            if (string.IsNullOrEmpty(propertyName))
                throw new ArgumentException("propertyName");

            if (backingField == null && newValue == null)
                return;

            if (backingField != null && backingField.Equals(newValue))
                return;

            if (beforeChange != null)
                beforeChange();

            backingField = newValue;

            OnPropertyChanged(propertyName);

            if (afterChange != null)
                afterChange();
        }
    }

我的程序流程:

  • StructureDesignViewModelComponentData.Components中獲取數據(樹結構數據)傳遞給視圖中的ItemsSource
  • 當我選擇GrandFatherComponent時, GrandFatherComponent.Children是下一個選擇器的ItemSource
  • 當我單擊SimpleTreeView/SelectedComponent的一個節點時,我調用 function Appear將節點名稱分配給SelectedComponentStructure

我的問題是SelectedComponentStructure已更改,但界面未更新。

謝謝閱讀! 此致!

結構設計視圖模型

public class StructureDesignViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

     string selectedComponentStructure;
     public string SelectedComponentStructure
     {
        get
        {
            return selectedComponentStructure;
        }
        set
        {
            selectedComponentStructure = value;
            SetPropertyValue(ref selectedComponentStructure, value);
        }

     }

    protected void OnPropertyChanges([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected void SetPropertyValue<T>(ref T bakingFiled, T value, [CallerMemberName] string proertyName = null)
    {
        bakingFiled = value;
        OnPropertyChanges(proertyName);

    }

}

試試這個方法。。

暫無
暫無

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

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