- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有默认的 MasterDetailPage
项目,其中有一个 ItemPage
和一个 ItemDetailPage
(当我单击一个项目时)。在我的 ItemDetailPage
中,我将 Item.Text
属性更改为 batata
并且我期望 ItemPage Item
文本发生变化,但它没有。如何更改我的 ItemDetailPage
中的属性并在 ItemPage
中也更改它?
<StackLayout>
<ListView x:Name="ItemsListView"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
RefreshCommand="{Binding LoadItemsCommand}"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement"
ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="10">
<Label Text="{Binding Text}"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemTextStyle}"
FontSize="16" />
<Label Text="{Binding Description}"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemDetailTextStyle}"
FontSize="13" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
public partial class ItemsPage : ContentPage
{
ItemsViewModel viewModel;
ItemDetailViewModel itemViewModel;
public ItemsPage()
{
InitializeComponent();
BindingContext = viewModel = new ItemsViewModel();
}
async void OnItemSelected(object sender, SelectedItemChangedEventArgs args)
{
this.BindingContext = null;
var item = args.SelectedItem as Item;
if (item == null)
return;
if(itemViewModel == null)
itemViewModel = new ItemDetailViewModel(item);
await Navigation.PushAsync(new ItemDetailPage(itemViewModel));
// Manually deselect item.
ItemsListView.SelectedItem = null;
this.BindingContext = viewModel;
}
protected override void OnAppearing()
{
base.OnAppearing();
if (viewModel.Items.Count == 0)
viewModel.LoadItemsCommand.Execute(null);
}
}
<StackLayout Spacing="20" Padding="15">
<Label Text="Text:" FontSize="Medium" />
<Label Text="{Binding Item.Text}" FontSize="Small"/>
<Label Text="Description:" FontSize="Medium" />
<Label Text="{Binding Item.Description}" FontSize="Small"/>
</StackLayout>
public partial class ItemDetailPage : ContentPage
{
ItemDetailViewModel viewModel;
public ItemDetailPage(ItemDetailViewModel viewModel)
{
InitializeComponent();
viewModel.Item.Text = "batata";
BindingContext = this.viewModel = viewModel;
}
}
项目 View 模型
public class ItemsViewModel : BaseViewModel
{
public ObservableCollection<Item> Items { get; set; }
public Command LoadItemsCommand { get; set; }
public ItemsViewModel()
{
Title = "Browse";
Items = new ObservableCollection<Item>();
LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
MessagingCenter.Subscribe<NewItemPage, Item>(this, "AddItem", async (obj, item) =>
{
var newItem = item as Item;
Items.Add(newItem);
await DataStore.AddItemAsync(newItem);
});
}
async Task ExecuteLoadItemsCommand()
{
if (IsBusy)
return;
IsBusy = true;
try
{
Items.Clear();
var items = await DataStore.GetItemsAsync(true);
foreach (var item in items)
{
Items.Add(item);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
}
ItemsDetailViewModel
public class ItemDetailViewModel : BaseViewModel
{
public Item Item { get; set; }
public ItemDetailViewModel(Item item = null)
{
Title = item?.Text;
Item = item;
}
}
元素模型:
public class Item
{
public string Id { get; set; }
public string Text { get; set; }
public string Description { get; set; }
}
最佳答案
问题是您正在绑定(bind)到类 Item
的属性,这些属性不会通知它们的更改,例如 Text
和 Description
。因此,当属性值更改时, View 中的值不会更新。
可以通过implementing INotifyPropertyChanged
来解决在 Item
中:
public class Item : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Id { get; set; }
private string _text;
public string Text
{
get => _text;
set
{
if (_text != value)
{
_text = value;
NotifyPropertyChanged();
}
}
}
private string _description;
public string Description
{
get => _description;
set
{
if (_description != value)
{
_description = value;
NotifyPropertyChanged();
}
}
}
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
但是,我还建议您不要绑定(bind)到嵌套属性,因为这可能会产生问题。因此,无需绑定(bind)到 Item.Text
和 Item.Description
,只需直接绑定(bind)到 View 模型中的属性即可。
例如,在 ItemDetailViewModel
中,您可以创建两个名为 ItemText
和 ItemDescription
的属性:
public string ItemText => Item?.Text;
public string ItemDescription => Item?.Description;
<!-- Updated bindings -->
<StackLayout Spacing="20" Padding="15">
<Label Text="Text:" FontSize="Medium" />
<Label Text="{Binding ItemText}" FontSize="Small"/>
<Label Text="Description:" FontSize="Medium" />
<Label Text="{Binding ItemDescription}" FontSize="Small"/>
</StackLayout>
要确保这些属性在 Item
的相应属性更改时通知它们的更改,您需要订阅事件 Item.PropertyChanged
以便您可以传播更新:
// (Assuming the base viewmodel implements INotifyPropertyChanged the same way than Item)
public class ItemDetailViewModel : BaseViewModel
{
private Item _item;
public Item Item
{
get => _item;
set
{
if (_item != value)
{
if (_item != null)
{
// Unsubscribe from the old item
_item.PropertyChanged -= OnItemPropertyChanged;
}
_item = value;
NotifyPropertyChanged();
if (value != null)
{
// Subscribe to the new item
value.PropertyChanged += OnItemPropertyChanged;
}
// Since the entire item has changed, we notify
// about changes in all the dependant properties
Title = Item?.Text;
NotifyPropertyChanged(nameof(ItemText));
NotifyPropertyChanged(nameof(ItemDescription));
}
}
}
public string ItemText => Item?.Text;
public string ItemDescription => Item?.Description;
public ItemDetailViewModel(Item item = null)
{
Item = item;
}
private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// When a property of the item changes, we propagate the changes
// to the properties of this viewmodel that now depend on it
if (e.PropertyName == nameof(Item.Text))
{
Title = Item?.Text;
NotifyPropertyChanged(nameof(ItemText));
}
else if (e.PropertyName == nameof(Item.Description))
{
NotifyPropertyChanged(nameof(ItemDescription));
}
}
}
这段代码有点乱,可以改进使其更优雅,但我希望你能理解。
关于c# - 如何更改 ViewModel 属性并将其保存到我的所有页面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56042731/
你能比较一下属性吗 我想禁用文本框“txtName”。有两种方式 使用javascript,txtName.disabled = true 使用 ASP.NET, 哪种方法更好,为什么? 最佳答案 我
Count 属性 返回一个集合或 Dictionary 对象包含的项目数。只读。 object.Count object 可以是“应用于”列表中列出的任何集合或对
CompareMode 属性 设置并返回在 Dictionary 对象中比较字符串关键字的比较模式。 object.CompareMode[ = compare] 参数
Column 属性 只读属性,返回 TextStream 文件中当前字符位置的列号。 object.Column object 通常是 TextStream 对象的名称。
AvailableSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。 object.AvailableSpace object 应为 Drive 
Attributes 属性 设置或返回文件或文件夹的属性。可读写或只读(与属性有关)。 object.Attributes [= newattributes] 参数 object
AtEndOfStream 属性 如果文件指针位于 TextStream 文件末,则返回 True;否则如果不为只读则返回 False。 object.A
AtEndOfLine 属性 TextStream 文件中,如果文件指针指向行末标记,就返回 True;否则如果不是只读则返回 False。 object.AtEn
RootFolder 属性 返回一个 Folder 对象,表示指定驱动器的根文件夹。只读。 object.RootFolder object 应为 Dr
Path 属性 返回指定文件、文件夹或驱动器的路径。 object.Path object 应为 File、Folder 或 Drive 对象的名称。 说明 对于驱动器,路径不包含根目录。
ParentFolder 属性 返回指定文件或文件夹的父文件夹。只读。 object.ParentFolder object 应为 File 或 Folder 对象的名称。 说明 以下代码
Name 属性 设置或返回指定的文件或文件夹的名称。可读写。 object.Name [= newname] 参数 object 必选项。应为 File 或&
Line 属性 只读属性,返回 TextStream 文件中的当前行号。 object.Line object 通常是 TextStream 对象的名称。 说明 文件刚
Key 属性 在 Dictionary 对象中设置 key。 object.Key(key) = newkey 参数 object 必选项。通常是 Dictionary 
Item 属性 设置或返回 Dictionary 对象中指定的 key 对应的 item,或返回集合中基于指定的 key 的&
IsRootFolder 属性 如果指定的文件夹是根文件夹,返回 True;否则返回 False。 object.IsRootFolder object 应为&n
IsReady 属性 如果指定的驱动器就绪,返回 True;否则返回 False。 object.IsReady object 应为 Drive&nbs
FreeSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。只读。 object.FreeSpace object 应为 Drive 对象的名称。
FileSystem 属性 返回指定的驱动器使用的文件系统的类型。 object.FileSystem object 应为 Drive 对象的名称。 说明 可
Files 属性 返回由指定文件夹中所有 File 对象(包括隐藏文件和系统文件)组成的 Files 集合。 object.Files object&n
我是一名优秀的程序员,十分优秀!