带有ObservableCollection的Xamarin Custom BindableProperty

时间:2016-04-14 08:06:44

标签: c# mvvm xamarin xamarin.forms

我正在尝试创建一个"桌面"页面,显示图标(程序)。

现在基本的想法是使用3x3网格,每个Cell代表一个图标点。

我过去只是直接从我的ViewModel调用View,但我想保持对MVVM的忠诚,并且我想在自定义Grid类中使用DataBinding和ObservableCollection来尝试使用它。

这是我的代码

ViewModel.cs

/*
ViewModel for the DashboardView
*/
public class DashboardViewModel : ViewModelBase
{
    INavigationService navigation;
    INetworkService network;

    public DashboardViewModel(INavigationService _navigation,
           INetworkService _network
           )
    {
        navigation = _navigation;
        network = _network;
        //modelService = _modelService;

        Startup();
    }

    /*
    Called when the application starts
    */
    public async void Startup()
    {
        //Bunch of network mumbojumbo that returns a bunch of services as JSON

        IList<JToken> results = result["data"]["services"].Children().ToList();
        foreach (JToken r in results)
        {
            ServiceModel temp = JsonConvert.DeserializeObject<ServiceModel>(r.ToString());
            Services.Add(temp);
            Debug.WriteLine(r);
        }
    }

    /*
    Holds all services displayed on the dashboard
    */
    public IList<ServiceModel> Services { get; } = new ObservableCollection<ServiceModel>();

这是View.cs中的相关代码

        serviceBoard = new DashboardDesktop()
        {
            VerticalOptions = LayoutOptions.FillAndExpand,
            HorizontalOptions = LayoutOptions.FillAndExpand,
            BackgroundColor = Color.FromRgb(0.94, 0.94, 0.94),

            RowDefinitions =
            {
                new RowDefinition() { Height = new GridLength(0.333, GridUnitType.Star) },
                new RowDefinition() { Height = new GridLength(0.333, GridUnitType.Star) },
                new RowDefinition() { Height = new GridLength(0.333, GridUnitType.Star) }
            },

            ColumnDefinitions =
            {
                new ColumnDefinition() { Width = new GridLength(0.333, GridUnitType.Star) },
                new ColumnDefinition() { Width = new GridLength(0.333, GridUnitType.Star) },
                new ColumnDefinition() { Width = new GridLength(0.333, GridUnitType.Star) }
            }
        };

        serviceBoard.SetBinding(DashboardDesktop.ServiceIconsProperty, "Services");

这是自定义网格类,我尝试创建我的ObservableCollection应绑定到的

的ServiceIcon属性
public class DashboardDesktop : Grid
{
    public static readonly BindableProperty ServiceIconsProperty =
         BindableProperty.Create
        (
        "ServiceIconsProperty",
        typeof(IList<ServiceModel>),
        typeof(DashboardDesktop),
        null,
        BindingMode.OneWay,
        (bindable, value) =>
        {
            return true;
        },
        (bindable, oldValue, newValue) =>
        {
            //do stuffs here
            //This is random stuff so I could add a breakpoint here
            int x = 10;
            var b = (IList<ServiceModel>)newValue;

            //Determine if an service have been removed or added
        });

    private IList<ServiceModel> Services { set; get; }


    public DashboardDesktop()
    {

    }
}

现在我试图在&#34; OnChanged&#34;内部设置一个断点。 ServiceIconProperty中的lambda函数,但它永远不会停在那里,即使我在ViewModel的ObservableCollection中添加了很多元素

我做错了什么?

2 个答案:

答案 0 :(得分:1)

你做错了几件事。

  1. 您正在创建Binding,但没有为其提供绑定来源 (有多种方法可以做到这一点)。
  2. BindableProperty.Create()的propertyName参数不应包含&#34;属性&#34;后缀。
  3. 没有理由包含&#34;服务&#34;在DashboardDesktop课程上收集。
  4. 您不能为ServiceIcons属性提供任何视觉效果。
  5. 要解决第一个问题,您只需将BindingSource的{​​{1}}设置为viewmodel的实例使用serviceBoard的不同重载即可允许您指定Source对象。

    第四个也非常重要 - 但也许您打算在评论SetBinding()所在的房产回调中插入/删除视觉儿童?

    无论如何,我不确定我是否会首先采用这种整体方法。相反,定义您自己的自定义模板化布局容器会更清晰(更多的是在XAML的精神中)。基本上,从//Determine if an service have been removed or added继承子类并相应地添加基于网格的定位逻辑,并添加Layout<View>ItemsSource。您应该能够查看内置的ItemTemplate类,了解Xamarin如何在那里实现这些功能并从中借用。

答案 1 :(得分:0)

您正在绑定集合,而不是集合的内容。

所以这个绑定只被调用一次(在它被创建时),而不再被调用。

在服务的setter中,您必须订阅更改您收到的ObservableCollection对象的事件。