gpt4 book ai didi

c# - 如何更改 ViewModel 属性并将其保存到我的所有页面?

转载 作者:行者123 更新时间:2023-11-30 22:54:41 26 4
gpt4 key购买 nike

我有默认的 MasterDetailPage 项目,其中有一个 ItemPage 和一个 ItemDetailPage(当我单击一个项目时)。在我的 ItemDetailPage 中,我将 Item.Text 属性更改为 batata 并且我期望 ItemPage Item 文本发生变化,但它没有。如何更改我的 ItemDetailPage 中的属性并在 ItemPage 中也更改它?

ItemPage Xaml 代码

<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 的属性,这些属性不会通知它们的更改,例如 TextDescription。因此,当属性值更改时, 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.TextItem.Description,只需直接绑定(bind)到 View 模型中的属性即可。

例如,在 ItemDetailViewModel 中,您可以创建两个名为 ItemTextItemDescription 的属性:

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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com