如何将 MVVMCross 与 C# 的标记绑定
Posted
技术标签:
【中文标题】如何将 MVVMCross 与 C# 的标记绑定【英文标题】:How to bind MVVMCross with Markup for C# 【发布时间】:2021-07-06 05:52:21 【问题描述】:我正在尝试使用 Xamarin 社区工具包中的 C# markup extensions 创建 Xamarin.Forms 视图,但想使用 MvvmCross 绑定视图。
我有一个 MvxContentPage 的工作解决方案,但我不确定每次设置 ViewModel 时调用 Bind 是正确的方法。还有更好的地方吗?
这是我的“工作”内容页面
[MvxTabbedPagePresentation(WrapInNavigationPage = true, Title = "Equipment")]
public sealed class EquipmentPage : MvxContentPage<EquipmentViewModel>
private ListView _listView;
public EquipmentPage()
Build();
protected override void OnViewModelSet()
base.OnViewModelSet();
Bind();
private void Build()
//On<ios>().SetLargeTitleDisplay(LargeTitleDisplayMode.Always);
// Xamarin.Forms.DebugRainbows.DebugRainbow.SetShowColors(this, true);
Visual = VisualMarker.Material;
Content = EquipmentList.Assign(out _listView);
private void Bind()
var set = CreateBindingSet();
set.Bind(_listView).For(v => v.IsRefreshing)
.To(vm => vm.IsRefreshing);
set.Bind(_listView).For(v => v.RefreshCommand)
.To(nameof(ViewModel.LoadData));
set.Bind(_listView).For(v => v.ItemsSource)
.To(vm => vm.Equipment);
set.Apply();
private ListView EquipmentList => new ListView(ListViewCachingStrategy.RecycleElement)
// RowHeight = 100,
HasUnevenRows = true,
IsPullToRefreshEnabled = true,
ItemTemplate = new DataTemplate(() => new EquipmentViewCell())
;
下一步是为 ListView 绑定一个 ViewCell。我还没有弄清楚如何使这个工作。 bindingContext 必须是 IMvxViewModel 吗?
这是我当前的 ViewCell
public class EquipmentViewCell : MvxViewCell
private Label _nameLabel, _modelLabel, _typeLabel;
public EquipmentViewCell()
Build();
enum EquipmentRow
Top,
Bottom
enum EquipmentColumn
Left,
Right
private void Build()
View = new Grid
RowDefinitions = GridRowsColumns.Rows.Define(
(EquipmentRow.Top, GridLength.Auto),
(EquipmentRow.Bottom, GridLength.Auto)),
ColumnDefinitions = GridRowsColumns.Columns.Define(
(EquipmentColumn.Left, GridLength.Star),
(EquipmentColumn.Right, GridLength.Auto)),
Children =
new StackLayout
Orientation = StackOrientation.Horizontal,
Children =
new Label
LineBreakMode = LineBreakMode.TailTruncation
.FontSize(20).Bold()
.StartExpand()
.Bind(nameof(EquipmentDto.Name))
.Assign(out _nameLabel),
new PancakeView
CornerRadius = new CornerRadius(8),
Content = new Label
TextColor = Color.White,
LineBreakMode = LineBreakMode.TailTruncation
.FontSize(16)
.Bind(convert: (EquipmentDto x) =>
var converter = new EquipmentStatusValueConverter();
return converter.Convert(x, typeof(string), null, null);
)
.Padding(new Thickness(8, 2, 8, 2))
.End()
.Bind(VisualElement.BackgroundColorProperty, convert: (EquipmentDto x) =>
var converter = new EquipmentStatusColorValueConverter();
return converter.Convert(x, typeof(Color), null, null);
),
.Row(EquipmentRow.Top).ColumnSpan(GridRowsColumns.All<EquipmentColumn>()),
new Label
LineBreakMode = LineBreakMode.TailTruncation,
TextColor = ColorPalette.SecondaryText
.FontSize(16)
.Row(EquipmentRow.Bottom).Column(EquipmentColumn.Left)
.Bind(nameof(EquipmentDto.Model))
.Assign(out _modelLabel),
new Label
LineBreakMode = LineBreakMode.TailTruncation,
HorizontalTextAlignment = TextAlignment.End,
TextColor = ColorPalette.SecondaryText
.FontSize(16)
.Row(EquipmentRow.Bottom).Column(EquipmentColumn.Right)
.Bind(nameof(EquipmentDto.Type.Name))
.Assign(out _typeLabel),
.Padding(new Thickness(16, 8, 16, 8));
private void Bind()
var set = this.CreateBindingSet<EquipmentViewCell, EquipmentDto>();
set.Bind(_nameLabel).To(vm => vm.Name);
set.Bind(_typeLabel).To(vm => vm.Type.Name);
set.Bind(_modelLabel).To(vm => vm.Type);
set.Apply();
我是否在正确的时间绑定?如何绑定 ViewCell?
【问题讨论】:
【参考方案1】:目前行之有效的方法。
MvxContentPage
:使用OnViewModelChanged
触发Bind()
函数。
MvxViewCell
:使用OnBindingContextChanged
触发Bind()
函数。
如果绑定已经完成,我还会添加一些逻辑来防止绑定。
private void Bind()
if (_didBind) return;
_didBind = true;
var set = CreateBindingSet();
...
set.Apply();
如果这不正确,请告诉我。
更新:这不适用于 ViewCell。项目现在出现在错误的单元格中。 :(
【讨论】:
以上是关于如何将 MVVMCross 与 C# 的标记绑定的主要内容,如果未能解决你的问题,请参考以下文章
如何使用MvvmCross将Android TextView绑定到Click事件
MvvmCross Visibility 插件不会隐藏我的 TextView