- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将我的应用程序转换为 MVVM 架构,但我遇到了 itemsource 问题。没有可用的命令属性。
我应该如何将 itemtapped 和 Menuitem clicked 转换为 MVVM 命令?当前使用 FRESHMVVM。我在谷歌搜索时找到了一些解决方案,但它们对此似乎非常复杂。
<ContentPage.Resources>
<ResourceDictionary>
<converters:StatusTextConverter x:Key="IntStatusToTextConverter" />
<converters:DateTextConverter x:Key="DateToTextConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ListView ItemsSource="{Binding Issues}" ItemTapped="OnEventSelected" SeparatorColor="#444444" RowHeight="90" IsPullToRefreshEnabled="True" IsRefreshing="{Binding IsBusy}" RefreshCommand="{Binding PullRefreshCommand}" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<ViewCell.ContextActions>
<MenuItem Clicked="OnDelete" Text="Delete" IsDestructive="True" />
</ViewCell.ContextActions>
<ViewCell.View>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Grid.Row="0" Grid.RowSpan="3" Grid.Column="0" Source="{Binding SeverityImagePath}" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="70"/>
<Image Grid.Row="0" Grid.RowSpan="3" Grid.Column="2" Source="{Binding StatusImagePath}" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="60"/>
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Title}" LineBreakMode="TailTruncation" YAlign="Center" VerticalOptions="Start" Font="Bold, Medium"/>
<Label Grid.Row="1" Grid.Column="1" Text="{Binding Created, Converter={StaticResource DateToTextConverter}}" YAlign="Center" VerticalOptions="Start" Font="Medium"/>
<Label Grid.Row="2" Grid.Column="1" Text="{Binding Description}" LineBreakMode="WordWrap" YAlign="Start" VerticalOptions="Start" Font="Small"/>
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
页面模型方法
public async void OnEventSelected(object o, ItemTappedEventArgs e)
{
if (IsBusy)
return;
var item = e.Item as IssueModel;
if (item != null)
{
MessagingCenter.Subscribe<IssuePageModel>(this, "refresh", async (sender) =>
{
MessagingCenter.Unsubscribe<IssueListPageModel>(this, "refresh");
await OnRefreshContent();
});
IssuePageModel page = null;
await Task.Run(() =>
{
UserDialogs.Instance.ShowLoading("Loading event...", maskType: MaskType.Clear);
// Does lost of stuff, So show loading message
UserDialogs.Instance.HideLoading();
});
if (item != null)
await CoreMethods.PushPageModel<IssuePageModel>(item);
}
}
public async void OnDelete(object sender, EventArgs e)
{
var mi = ((MenuItem)sender);
IssueModel issue = mi.BindingContext as IssueModel;
if (issue != null)
{
IsBusy = true;
bool bDeleted = await Task.Run(() =>
{
try
{
App.Client.DeleteIssue(issue.Id);
return Issues.Remove(issue);
}
catch (Exception /*ex*/)
{
return false;
}
});
if (bDeleted == false)
await CoreMethods.DisplayAlert("Failed", "Failed to remove item", "Continue");
IsBusy = false;
}
}
最佳答案
好的,所以首先,将以下两个类添加到您的项目中——无耻地从我评论中的示例中窃取:
using System;
using Xamarin.Forms;
namespace EventToCommandBehavior
{
public class BehaviorBase<T> : Behavior<T> where T : BindableObject
{
public T AssociatedObject { get; private set; }
protected override void OnAttachedTo(T bindable)
{
base.OnAttachedTo(bindable);
AssociatedObject = bindable;
if (bindable.BindingContext != null)
{
BindingContext = bindable.BindingContext;
}
bindable.BindingContextChanged += OnBindingContextChanged;
}
protected override void OnDetachingFrom(T bindable)
{
base.OnDetachingFrom(bindable);
bindable.BindingContextChanged -= OnBindingContextChanged;
AssociatedObject = null;
}
void OnBindingContextChanged(object sender, EventArgs e)
{
OnBindingContextChanged();
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
BindingContext = AssociatedObject.BindingContext;
}
}
}
和
using System;
using System.Reflection;
using System.Windows.Input;
using Xamarin.Forms;
namespace EventToCommandBehavior
{
public class EventToCommandBehavior : BehaviorBase<View>
{
Delegate eventHandler;
public static readonly BindableProperty EventNameProperty =
BindableProperty.Create("EventName",
typeof(string),
typeof(EventToCommandBehavior),
null,
propertyChanged: OnEventNameChanged);
public static readonly BindableProperty CommandProperty =
BindableProperty.Create("Command",
typeof(ICommand),
typeof(EventToCommandBehavior),
null);
public static readonly BindableProperty CommandParameterProperty =
BindableProperty.Create("CommandParameter",
typeof(object),
typeof(EventToCommandBehavior),
null);
public static readonly BindableProperty InputConverterProperty =
BindableProperty.Create("Converter",
typeof(IValueConverter),
typeof(EventToCommandBehavior),
null);
public string EventName
{
get { return (string)GetValue(EventNameProperty); }
set { SetValue(EventNameProperty, value); }
}
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public IValueConverter Converter
{
get { return (IValueConverter)GetValue(InputConverterProperty); }
set { SetValue(InputConverterProperty, value); }
}
protected override void OnAttachedTo(View bindable)
{
base.OnAttachedTo(bindable);
RegisterEvent(EventName);
}
protected override void OnDetachingFrom(View bindable)
{
DeregisterEvent(EventName);
base.OnDetachingFrom(bindable);
}
void RegisterEvent(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return;
}
EventInfo eventInfo = AssociatedObject.GetType().GetRuntimeEvent(name);
if (eventInfo == null)
{
throw new ArgumentException(string.Format("EventToCommandBehavior: Can't register the '{0}' event.", EventName));
}
MethodInfo methodInfo = typeof(EventToCommandBehavior).GetTypeInfo().GetDeclaredMethod("OnEvent");
eventHandler = methodInfo.CreateDelegate(eventInfo.EventHandlerType, this);
eventInfo.AddEventHandler(AssociatedObject, eventHandler);
}
void DeregisterEvent(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return;
}
if (eventHandler == null)
{
return;
}
EventInfo eventInfo = AssociatedObject.GetType().GetRuntimeEvent(name);
if (eventInfo == null)
{
throw new ArgumentException(string.Format("EventToCommandBehavior: Can't de-register the '{0}' event.", EventName));
}
eventInfo.RemoveEventHandler(AssociatedObject, eventHandler);
eventHandler = null;
}
void OnEvent(object sender, object eventArgs)
{
if (Command == null)
{
return;
}
object resolvedParameter;
if (CommandParameter != null)
{
resolvedParameter = CommandParameter;
}
else if (Converter != null)
{
resolvedParameter = Converter.Convert(eventArgs, typeof(object), null, null);
}
else
{
resolvedParameter = eventArgs;
}
if (Command.CanExecute(resolvedParameter))
{
Command.Execute(resolvedParameter);
}
}
static void OnEventNameChanged(BindableObject bindable, object oldValue, object newValue)
{
var behavior = (EventToCommandBehavior)bindable;
if (behavior.AssociatedObject == null)
{
return;
}
string oldEventName = (string)oldValue;
string newEventName = (string)newValue;
behavior.DeregisterEvent(oldEventName);
behavior.RegisterEvent(newEventName);
}
}
}
EventToCommandBehavior 类可用于从具有从 View
派生的任何类的事件中调用命令。您可以像这样将它附加到您的 ListView
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:behaviors="clr-namespace:EventToCommandBehavior"
x:Class="FormsBehaviors.Views.MainPage">
<ContentPage.Resources>
<ResourceDictionary>
<behaviors:SelectedItemEventArgsToSelectedItemConverter x:Key="SelectedItemConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<ListView ItemsSource="{Binding Thingies}">
<ListView.Behaviors>
<behaviors:EventToCommandBehavior EventName="ItemSelected"
Command="{Binding FooCommand}"
Converter="{StaticResource SelectedItemConverter}" />
</ListView.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
转换器是可选的。如果省略它,将使用相关事件参数调用您的命令。在这种情况下,使用转换器从事件参数中提取所选项目并将其作为命令参数传递是有意义的。为了完整起见,这是转换器:
using System;
using System.Globalization;
using Xamarin.Forms;
namespace EventToCommandBehavior
{
public class SelectedItemEventArgsToSelectedItemConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var eventArgs = value as SelectedItemChangedEventArgs;
return eventArgs.SelectedItem;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
请记住,前两个类 - BehaviorBase
和 EventToCommandBehavior
不是 ListView
独有的,它们可以与派生自的任何类一起使用查看
。此外,如果您不能/不想使用事件参数,还有另一个属性 CommandParameter
可用于将显式参数传递给您要绑定(bind)的命令。有关详细信息,请参阅 EventToCommandBehavior
的 OnEvent
方法。
编辑:使用命令的说明。执行命令的 ViewModel 应该看起来像这样(不使用转换器)
public class MainVM
{
public ObservableCollection<Thingy> Thingies { get; set; }
public ICommand FooCommand { get; set; }
public MainVM()
{
Thingies = new ObservableCollection<Thingy>();
FooCommand = new Command(Bar);
}
private void Bar(object eventArgs)
{
var args = eventArgs as SelectedItemChangedEventArgs;
if (args == null)
return;
var selectedItem = args.SelectedItem;
}
}
关于c# - 如何创建 ItemSource Xamarin 命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49236497/
我有一个包含一些按钮和一个 ListView 的用户控件。 我希望我的自定义控件具有 ItemsSource直接绑定(bind)到 ListView 项目源的属性。 MyControl.xaml.cs
当从 Powershell 以编程方式将 WPF Combobox 的 ItemSource 设置为 DataRowCollection 时,只有一个条目,我收到此错误消息: Ausnahme bei
在 WPF 的 datagridview 中只显示列名但不显示行。我试过将 autogeneratecolumns="true" 放在 datagridview 中,但没有成功。我已经调试并检查了数据
在我的 ViewModel 上,我有 2 个属性(都实现了属性更改通知): CountryOfIssue Nationality 在我的 View 中,我有一个 CollectionViewSourc
我有一个 Roles 的列表我想在 DataGrid 中选择细胞 ComboBox . 我有 ObservableCollection Roles对于ComboBox在 ViewModel 中填充。
我正在使用 ItemsControl在 ItemContainerTemplate 中有一个对象列表...我还有一个 DataTemplate .里面DataTemplate我无法绑定(bind)到
当在文本框中键入并单击“添加员工”时,我希望它更新并显示到数据网格,我已经实现了 INotifyPropertyChanged 和 RelayCommand。我错过了什么没有填充数据。提前致谢这是我的
我的第一个 StackExchange 问题,如果我做错了什么,请告诉我。 我正在将旧的 winforms 代码转换为 WPF,并且一直在使用它们。我大部分时间都取得了成功,但我正在处理我的第一个涉及
我正在尝试将我的应用程序转换为 MVVM 架构,但我遇到了 itemsource 问题。没有可用的命令属性。 我应该如何将 itemtapped 和 Menuitem clicked 转换为 MVVM
在我的类(class) ResultEntity 中,如果我这样做: _resultMulti = new List(); 我看到以下错误消息: "Exception: Items collectio
这是我的情况: 存在一个 ObservableCollection 并且窗口中的一系列列表框显示了它们的绑定(bind)数据。 public Records myRecents; //... this
我有一个组合框,数据动态分配如下 我正在从数据库加载客户详细信息并将它们设置为列表框并分配给组合框,如下所示。 clientbox.DataContext = 运行后我可以在组合框中看到数据。这将
我有异常(exception): 使用 ItemsSource 时操作无效。改为使用 ItemsControl.ItemsSource 访问和修改元素。 最佳答案 您必须将项目添加到设置为 Items
在我的Xamarin.Forms应用程序中,我有一个简单的Contact类[Model]。在UI [ View ]中,存在一个显示联系人的ListView。在模型 View 类中,我有一个联系人列表(
我在带有 TreeView 的 Silverlight 4 应用程序中有一个 ChildWindow。 ItemSource 绑定(bind)到 ViewModel 中项目的 ObservableCo
我正在开发一个从 Web 服务获取数据并显示它的 Windows Phone 8 应用程序。 我有一个绑定(bind)到 LongListSelector 的通知列表,当用户滚动到末尾时,我想在其中显
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What is a NullReferenceException in .NET? 我有两个 ComboBo
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What is a NullReferenceException in .NET? 我有两个 ComboBo
我目前正在使用 Xamarin Forms,我正在使用从 github RESTAPI 获得的 post 方法.每当我尝试将数据应用到我的 ListView ItemsSource 时,我的应用程序就
在我使用 this.ProductList.ItemSource = null;: 清除数据网格后,此语句将给我 null 异常 salesItem = (from SalesItem item
我是一名优秀的程序员,十分优秀!