I want to update value in entry control inside ListView from another Pop up page using messageCenter approach. It is not working as expected as it is updating multiple items in list view.
My base page (PageA) has ListView
<ListView
x:Name="workList"
Grid.Row="2"
SeparatorColor="{DynamicResource AccentColor}"
ItemsSource="{ Binding WorkItems}"
Margin="5"
CachingStrategy="RecycleElement"
RowHeight="440"
SeparatorVisibility="Default"
SelectionMode="None"
HasUnevenRows="False">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<local:LoadItemPutawayTemplate />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
LoadItemPutAwayTemplate is my content view for ListView as below
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-
compatibility/2006"
mc:Ignorable="d"
x:Class="Sanipex.LoadItemPutawayTemplate">
<Grid
RowSpacing="0"
Padding="0"
Margin="0,10,0,0"
>
<Grid.RowDefinitions>
<RowDefinition
Height="*" />
<RowDefinition
Height="auto" />
</Grid.RowDefinitions>
<Entry
x:Name="OverrideLoc"
Grid.Row="0"
TextColor="Black"
WidthRequest="110"
Text="{Binding toLocation}"
HorizontalOptions="StartAndExpand"
VerticalOptions="Center"
FontAttributes="Bold"
PlaceholderColor="Black"
FontSize="20"/>
<Button
Grid.Row="1"
HorizontalOptions="Center"
x:Name="LocationBtn"
Text="Override Loc"
BackgroundColor="#25D366"
TextColor="{DynamicResource AccentColor}"
BorderColor="#25D366"
Style="{ StaticResource CircleActionButtonFlatStyle }"
Clicked="LocationBtn_Clicked"/>
</Grid>
On LocationBtn_Clicked i am calling the popup
private async void LocationBtn_Clicked(object sender, EventArgs e)
{
var AvailableLocationPopUp = new AvailableLocationsPopUp();
await PopupNavigation.Instance.PushAsync(AvailableLocationPopUp);
}
Below is my Pop up page (AvailableLocationsPopUp) button click method from where I am sending the message
private void PutawayBtn_Clicked(object sender, EventArgs e)
{
MessagingCenter.Send<AvailableLocationsPopUp, string>(this,
"Location", "XYZ");
}
As i have entry control in my contentView of LoadItemPutAwayTemplate, I am subscribing message in its constructor as below to update the value of entry control
public LoadItemPutawayTemplate()
{
InitializeComponent();
MessagingCenter.Subscribe<AvailableLocationsPopUp, string>(this,
"Location", async (sender, arg) =>
{
this.OverrideLoc.Text = arg;
}
}
But this is updating values to all ListView items which are showing on UI. I just want to update the value of item from where the pop up was initiated.
When you subscribe to the message in the template, then all the ListView items will receive the message. I have created a simple demo to simulate your app,the main code is:
LocationModel.cs
public class LocationModel: INotifyPropertyChanged
{
string toLocation;
public string ToLocation {
set { SetProperty(ref toLocation, value); }
get { return toLocation; }
}
bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Object.Equals(storage, value))
return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
LoadItemPutawayTemplate.xaml.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class LoadItemPutawayTemplate : ContentView
{
public LoadItemPutawayTemplate()
{
InitializeComponent();
}
private void LocationBtn_Clicked(object sender, EventArgs e)
{
LocationModel stringInThisCell = (LocationModel)((Button)sender).BindingContext;
System.Diagnostics.Debug.WriteLine("send msg current update = " + stringInThisCell.ToLocation);
string source = stringInThisCell.ToLocation;
string result = "XYZ";
string[] values = { source, result };
MessagingCenter.Send<LoadItemPutawayTemplate, string[]>(this, "Location", values);
}
}
LoadItemPutawayTemplate.xaml
<ContentView.Content>
<Grid
RowSpacing="0"
Padding="0"
Margin="0,2,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Entry
x:Name="OverrideLoc"
Grid.Column="0"
TextColor="Black"
WidthRequest="110"
Text="{Binding ToLocation}"
HorizontalOptions="StartAndExpand"
VerticalOptions="Center"
FontAttributes="Bold"
PlaceholderColor="Black"
FontSize="20"/>
<Button
Grid.Column="1"
HorizontalOptions="Center"
x:Name="LocationBtn"
Text="Override Loc"
BackgroundColor="#25D366"
TextColor="{DynamicResource AccentColor}"
BorderColor="#25D366"
Clicked="LocationBtn_Clicked"/>
</Grid>
</ContentView.Content>
MainPage.xaml.cs
public partial class MainPage : ContentPage
{
public List<LocationModel> WorkItems { get; set; }
public MainPage()
{
InitializeComponent();
WorkItems = new List<LocationModel>();
WorkItems.Add(new LocationModel { ToLocation = "Tomato"});
WorkItems.Add(new LocationModel { ToLocation = "Zucchini" });
WorkItems.Add(new LocationModel { ToLocation = "Tomato2"});
WorkItems.Add(new LocationModel { ToLocation = "Romaine2" });
WorkItems.Add(new LocationModel { ToLocation = "Zucchin2"});
MessagingCenter.Subscribe<LoadItemPutawayTemplate, string[]>(this,
"Location", async (sender, values) =>
{
string source = values[0];
string result = values[1];
for (int i = 0; i < WorkItems.Count; i++)
{
LocationModel model = WorkItems[i];
if (source.Equals(model.ToLocation)) {
model.ToLocation = result;
break;
}
}
});
workList.ItemsSource = WorkItems;
}
}
Note:
AvailableLocationsPopUp
, so I send the message when I click the Button.