我正在尝试创建一个"桌面"页面,显示图标(程序)。
现在基本的想法是使用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中添加了很多元素
我做错了什么?
答案 0 :(得分:1)
你做错了几件事。
Binding
,但没有为其提供绑定来源
(有多种方法可以做到这一点)。BindableProperty.Create()
的propertyName参数不应包含&#34;属性&#34;后缀。DashboardDesktop
课程上收集。ServiceIcons
属性提供任何视觉效果。要解决第一个问题,您只需将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对象的事件。