Does anyone encounter annoyed issue when update background color of cell in xamarin form?
I have notification list, when user clicks on item, it's marked as read then background color will be updated.
It works perfectly on android but iOS.
Most of the time the color is changed back to origin.
In the example, cell background is blue if notification is read.
When user clicks on cell, cell background should be red, but it's not changed most of time.
Notification Model
public class Notification : ObservableObject
{
private string _message;
private bool _isRead;
public string Message
{
get => _message;
set => SetProperty(ref _message, value);
}
public bool IsRead
{
get => _isRead;
set => SetProperty(ref _isRead, value);
}
}
ViewModel
public class MainPageViewModel : BaseViewModel
{
private ObservableCollection<Notification> _notifications;
public ObservableCollection<Notification> Notifications
{
get => _notifications;
set => SetProperty(ref _notifications, value);
}
public ICommand TappedCommand => new Command((o => OnTapped(o)));
public MainPageViewModel()
{
_notifications = new ObservableCollection<Notification>()
{
new Notification()
{
IsRead = false,
Message = "First notification"
},
new Notification()
{
IsRead = false,
Message = "Second notification"
},
new Notification()
{
IsRead = false,
Message = "Third notification"
},
new Notification()
{
IsRead = false,
Message = "Fourth notification"
}
};
}
private void OnTapped(object o)
{
if(!(o is Notification noti)) return;
noti.IsRead = true;
}
}
Page:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:NotificationTest"
x:Class="NotificationTest.MainPage">
<ContentPage.Content>
<ListView x:Name="NotiList" ItemsSource="{Binding Notifications}" ItemTapped="OnTapped" ItemSelected="OnSelected" CachingStrategy="RecycleElement">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid BackgroundColor="{Binding IsRead,Converter={StaticResource ReadToColorConverter}}">
<Label Text="{Binding Message}"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
Page code behind ( just work around to hide selected line color in listview
public partial class MainPage : ContentPage
{
private MainPageViewModel _vm;
public MainPage()
{
InitializeComponent();
_vm = new MainPageViewModel();
BindingContext = _vm;
}
private void OnTapped(object sender, ItemTappedEventArgs e)
{
_vm.TappedCommand.Execute(e.Item);
}
private void OnSelected(object sender, SelectedItemChangedEventArgs e)
{
NotiList.SelectedItem = null;
}
}
The problem was caused by the default behavior when selecting cell in iOS.
The default selected color will cover the red color , so it didn't get working.
Refer to my recent answer Here
Test
Related
I have a ListView in Xamarin Forms that has custom ViewCells with editors in them. I have a function subscribed to the editors' TextChanged events that checks the text for newlines and if it finds any, it removes them and unfocuses the editor. It works properly on Android, but on iOS, the editor gets unfocused whenever I type anything, not just newlines. How do I fix this?
The XAML for the page:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage 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"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
mc:Ignorable="d"
x:Class="Partylist.Views.ChecklistPage"
ios:Page.UseSafeArea="True">
...
<ContentPage.Content>
<!--Main layout of the page-->
<StackLayout>
<!--ListView of the checklist items-->
<ListView x:Name="ChecklistView"
HeightRequest="300"
HasUnevenRows="true"
ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<SwipeView>
<!--Swipe from the right to make some options
appear-->
<SwipeView.RightItems>
<SwipeItems>
<SwipeItem Invoked="OnDelete"
CommandParameter="{Binding .}"
Text="Delete"
BackgroundColor="#ff418b"
IsDestructive="true"/>
</SwipeItems>
</SwipeView.RightItems>
<!--This is the actual content-->
<StackLayout Orientation="Horizontal"
Padding="20,5"
VerticalOptions="FillAndExpand">
<ContentView Content="{Binding ItemCheckbox}"/>
<ContentView Content="{Binding ItemEditor}"
VerticalOptions="FillAndExpand"/>
</StackLayout>
</SwipeView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
...
</StackLayout>
</ContentPage.Content>
</ContentPage>
The code:
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Partylist.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ChecklistPage : ContentPage
{
// Struct for items on the checklist.
private struct Item
{
public Editor ItemEditor { get; set; }
public CheckBox ItemCheckbox { get; set; }
}
// Create a list of contact structs to populate the ListView.
ObservableCollection<Item> items;
// Flag for when an item is added to the list.
bool itemAdded = false;
...
// Override for OnAppearing().
protected override void OnAppearing()
{
// Makes the page appear.
base.OnAppearing();
// Set the page's title to be the name of the selected list.
Title = App.selectedList.Name;
// Make a toolbar item appear to access the Main Checklist
// unless we are already there.
if (App.selectedList.ListFile.Name.EndsWith(".mchec"))
{
ToolbarItems.Remove(MainChecklistButton);
}
// Set the binding context of the page to itself.
BindingContext = this;
// Start the timer for the tips banner if it is stopped.
App.tipTimer.Start();
// Set the banner's text to the current tip's sumamry.
tipLabel.Text = ((App)App.Current).CurrentTip.Summary;
OnPropertyChanged("CurrentTip");
// Subscribe the OnTipUpdate function to the tipUpdate event in the app
// class.
App.TipUpdate += OnTipUpdate;
// Make the ObservableCOllection reference something.
items = new ObservableCollection<Item>();
// Open a stream to the list that we want to display.
using (StreamReader listReader = new StreamReader(App.selectedList
.ListFile.FullName))
{
// Loop through the file and read data into the list.
while (!listReader.EndOfStream)
{
// Create a blank item.
Item newItem = new Item()
{
ItemEditor = new Editor()
{
Text = listReader.ReadLine(),
Placeholder = "New Item",
IsTabStop = true,
AutoSize = EditorAutoSizeOption.TextChanges,
WidthRequest = 300
},
ItemCheckbox = new CheckBox()
{
Color = App.selectedList.ListItemColor,
IsChecked = bool.Parse(listReader.ReadLine())
}
};
// Subscribe OnTextChanged() to the new item's editor's
// TextChanged event.
newItem.ItemEditor.TextChanged += OnTextChanged;
// Add the new item to the list.
items.Add(newItem);
// Make the ListView update.
OnPropertyChanged("contacts");
}
// Once everything is loaded, close the file.
listReader.Close();
ChecklistView.ItemsSource = items;
}
}
...
// Function for when the "Add New Contact" button is clicked.
private void OnAddNewItemClicked(object sender, EventArgs e)
{
// Create a blank item.
Item newItem = new Item()
{
ItemEditor = new Editor()
{
Placeholder = "New Item",
IsTabStop = true,
AutoSize = EditorAutoSizeOption.TextChanges,
WidthRequest = 300
},
ItemCheckbox = new CheckBox()
{
Color = App.selectedList.ListItemColor,
IsChecked = false
}
};
// Subscribe OnTextChanged() to the new item's editor's
// TextChanged event.
newItem.ItemEditor.TextChanged += OnTextChanged;
// Add the new contact to the list.
items.Add(newItem);
// Set the "itemAdded" flag to true.
itemAdded = true;
// Make the ListView update.
ChecklistView.ItemsSource = items;
OnPropertyChanged("items");
// Select the new item so it can be focused.
ChecklistView.SelectedItem = items.ElementAt(items.Count - 1);
}
// Function for when an item is selected, used to set the focus to
// a newly added item in the list.
private async void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
// Only runs this if an item was added (as opposed to being
// read in from the file).
if (itemAdded)
{
if (e.SelectedItem == null) return;
await Task.Delay(100); // Change the delay time if Focus() doesn't work.
((Item)e.SelectedItem).ItemEditor.Focus();
ChecklistView.SelectedItem = null;
itemAdded = false;
}
}
// Function for when the text of an editor is changed.
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
// If the editor's text now contains a newline...
if (((Editor)sender).Text.Contains("\n"))
{
// Split the string at the newline and recombine it. This
// will get rid of the newline.
string[] tempArray = ((Editor)sender).Text.Split('\n');
string tempStr = "";
foreach (string str in tempArray)
{
tempStr += str;
}
((Editor)sender).Text = tempStr;
// Unfocus the editor.
((Editor)sender).Unfocus();
}
// Force the cell's size to update (it is the parent of the
// parent of the parent of the parent of the editor).
((ViewCell)((Editor)sender).Parent.Parent.Parent.Parent).ForceUpdateSize();
}
...
}
}
Calling ForceUpdateSize will cause Editor unfocus. You can put the ForceUpdateSize into a Task.Run method and call focus after ForceUpdateSize();.
private async void OnTextChanged(object sender, TextChangedEventArgs e)
{
//...
await Task.Run(()=>{
((ViewCell)((Editor)sender).Parent.Parent.Parent.Parent).ForceUpdateSize();
});
((Editor)sender).Focus();
}
I replaced the ListView with a CollectionView and that seems to have fixed the problem.
Also, the CollectionView doesn't have a HasUnevenRows property, so that will have to be removed and it doesn't use cells, so the ForceUpdateSize() method will also have to be removed.
I'm creating app in UWP and i have question.
Can I somehow connection MVVM Light with SelectionChanged event (e.g. ListView) or with other event?
I would like that when I will click on some Item in ListView then I call SelectionChanged.
How do I do?
You can write the Method in ViewModel ,and use the x:bind to connection ViewModel.
The MVVMLight's method is use in WPF that cant bind the event in Method.
UWP can use x:bind to bind the UI event to ViewModel.
The sample:
XAML:
<ListView SelectionChanged = "{x:bind view.SelectionChanged }"/>
XAML.cs:
private ViewModel View{set;get;}
ViewModel:
public void SelectionChanged()
{
}
You can use ItemClick event that will run when you click the ListViewItem .
Inside your viewmodel something *.cs
public class RelayCommand : ICommand
{
private Predicate<object> _canExecute;
private Action<object> _execute;
public RelayCommand(Predicate<object> canExecute, Action<object> execute)
{
this._canExecute = canExecute;
this._execute = execute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
public class MyViewModel
{
private ICommand _doSelectionChangedCommand;
public ICommand DoSelectionChangedCommand
{
get
{
if (_doSelectionChangedCommand == null)
{
_doSelectionChangedCommand = new RelayCommand(
p => this.CanSelectionChanged,
p => this.DoSomeImportantMethod());
}
return _doSomething;
}
}
}
In your viewSomemthing.xaml
--For namespace
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
--Then go down to your control, we'll use Combobox as an example
<ComboBox ... />
<i:Interaction.Triggers>
<EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding DoSelectionChangedCommand}"/>
</EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
I am developing a Windows Universal App which is hosting a web app using webview.
steps are followed as like.
Creating a Blank universal window app. Creating a Splash screen. Set
splash screen as starting page. After all activity i would like to
navigate the Main page which is having a web view control.
Setting a url example "http:www.google.come" as source for the web view. everything it works a fine but the main page takes time, where i would like to see the same splash screen till it loads.
Code for Navigation i am using
this.Frame.Navigate(typeof(MainPage));
full source code
public sealed partial class ExtentedSpash : Page
{
public ProgressMessage Progress;
public ExtentedSpash()
{
this.InitializeComponent();
Progress = ProgressMessage.GetMessage();
DataContext = Progress;
Window.Current.Activate();
Loaded += Splash_Loaded;
}
private async void Splash_Loaded(object sender, RoutedEventArgs e)
{
await Initialize();
Window.Current.Activate();
await ClearBrowserCache();
Window.Current.Activate();
//Task.WaitAll(TaskList.ToArray());
await StartApplication();
}
public async Task Initialize()
{
Progress.ActionMessage = "Initialize the controls";
await Task.Delay(TimeSpan.FromSeconds(10));
}
public async Task ClearBrowserCache()
{
Progress.ActionMessage = "Clear Browser Cache";
await Task.Delay(TimeSpan.FromSeconds(10));
}
public async Task StartApplication()
{
Progress.ActionMessage = "Loading";
await Task.Delay(TimeSpan.FromSeconds(10));
this.Frame.Navigate(typeof(MainPage));
}
private void btnMain_Click(object sender, RoutedEventArgs e)
{
}
}
public class ProgressMessage : INotifyPropertyChanged
{
private string statusMessage;
public string StatusMessage
{
get { return statusMessage; }
set
{
statusMessage = value;
RaiseProperChanged();
}
}
private string actionMessage;
public string ActionMessage
{
get { return actionMessage; }
set
{
actionMessage = value;
RaiseProperChanged();
}
}
private bool showProgress;
public bool ShowProgress
{
get { return showProgress; }
set { showProgress = value;
RaiseProperChanged();
}
}
public static ProgressMessage GetMessage()
{
var msg = new ProgressMessage()
{
StatusMessage = "Initializing Application",
ActionMessage = "One moment please...",
showProgress = true
};
return msg;
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaiseProperChanged(
[CallerMemberName] string caller = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(caller));
}
}
}
}
I want "On Loading" message should show til it fully loads the application.
As we've discussed, if you just want to cover the WebView when it's source is not complete loaded, you can do it like this:
<Page.Resources>
<Storyboard x:Key="MyTextSTD" x:Name="MyTextSTD" RepeatBehavior="Forever">
<ColorAnimationUsingKeyFrames Storyboard.TargetName="tbbrush" Storyboard.TargetProperty="Color" Duration="0:0:10">
<DiscreteColorKeyFrame KeyTime="0:0:0" Value="Red" />
<LinearColorKeyFrame KeyTime="0:0:5" Value="Blue" />
<LinearColorKeyFrame KeyTime="0:0:10" Value="Purple" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<WebView Source="https://msdn.microsoft.com/library/windows/apps/xaml/mt244352.aspx" NavigationCompleted="WebView_NavigationCompleted">
</WebView>
<Grid x:Name="loadingGrid" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Visibility="Visible">
<TextBlock Text="On Loading..." FontSize="50" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock.Foreground>
<SolidColorBrush x:Name="tbbrush" />
</TextBlock.Foreground>
</TextBlock>
</Grid>
</Grid>
And code behind:
public MainPage()
{
this.InitializeComponent();
MyTextSTD.Begin();
}
private void WebView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
loadingGrid.Visibility = Visibility.Collapsed;
}
Here is quite simple, I use a TextBlock and some color animation to show the message. And this message will disappear when the source of WebView is fully loaded.
tl;dr: How do I use swipe to show buttons in Xamarin Forms like the iOS mail app
I am trying to implement swipe to show buttons for a Xamarin Forms iOS app similar to the UI of the iOS mail app or this https://components.xamarin.com/view/swtableviewcell. That component among many other examples I found look great for iOS native implementations but I need to show this UI via Xamarin forms.
Currently I have a custom swipe gesture recognizer like this:
[assembly: ExportRenderer(typeof(SwipeViewCell), typeof(SwipeIosRenderer))]
namespace MyApp.iOS.Renderers
{
public class SwipeIosRenderer : ViewCellRenderer
{
UISwipeGestureRecognizer swipeRightGestureRecognizer;
UISwipeGestureRecognizer swipeLeftGestureRecognizer;
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
swipeRightGestureRecognizer = new UISwipeGestureRecognizer(() => UpdateRight()) { Direction = UISwipeGestureRecognizerDirection.Right };
swipeLeftGestureRecognizer = new UISwipeGestureRecognizer(() => UpdateLeft()) { Direction = UISwipeGestureRecognizerDirection.Left };
if (e.NewElement == null)
{
if (swipeRightGestureRecognizer != null)
{
this.RemoveGestureRecognizer(swipeRightGestureRecognizer);
}
if (swipeLeftGestureRecognizer != null)
{
this.RemoveGestureRecognizer(swipeLeftGestureRecognizer);
}
}
if (e.OldElement == null)
{
this.AddGestureRecognizer(swipeRightGestureRecognizer);
this.AddGestureRecognizer(swipeLeftGestureRecognizer);
}
}
private void UpdateLeft()
{
Console.WriteLine("Left swipe");
}
private void UpdateRight()
{
Console.WriteLine("Right swipe");
}
}
That is bound to viewcells in a list. Now that I can recognize the "swipe" gesture I need help on how to actually move the view cell over and show a button like the examples I gave above?
It would be great to able to do this within the views XAML but am open to anything. I have a UpdateLeft and UpdateRight function that gets called on the respective swipe motions too if that can be used?
**EDIT: I need to do this for both left AND right swipe. ContextActions only provide the left swipe functionality.
Hope that makes sense!
Would Context Actions work for you? I haven't tried on other platforms, but on iOS it will create a swipe menu just like the Mail app. You should be able to use XAML and bind to command properties as well.
Edit:
Since you clarified that you need the left and right side swipe buttons that do not exist in the ContextActions, you could utilize the existing SWTableViewCell component that already has the desired behavior and adapt it to Xamarin.Forms.
iOSRenderer:
public class SwipeIosRenderer : TextCellRenderer
{
static NSString rid = new NSString("SWTableViewCell");
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
var forms_cell = (SwipeCell)item;
SWTableViewCell native_cell = reusableCell as SWTableViewCell;
if (native_cell == null)
{
native_cell = new SWTableViewCell(UITableViewCellStyle.Default, rid);
if (forms_cell != null)
{
var cellDelegate = new CellDelegate(forms_cell);
native_cell.Delegate = cellDelegate;
if (forms_cell.LeftContextActions != null)
{
var left = new NSMutableArray();
foreach (var btn in forms_cell.LeftContextActions)
{
AddButton(left, btn);
}
native_cell.LeftUtilityButtons = NSArray.FromArray<UIButton>(left);
}
if (forms_cell.RightContextActions != null)
{
var right = new NSMutableArray();
foreach (var btn in forms_cell.RightContextActions)
{
AddButton(right, btn);
}
native_cell.RightUtilityButtons = NSArray.FromArray<UIButton>(right);
}
}
native_cell.TextLabel.Text = forms_cell.Text;
}
var fs = forms_cell.ImageSource as FileImageSource;
if (fs != null)
{
native_cell.ImageView.Image = UIImage.FromBundle(fs.File);
}
return native_cell;
}
void AddButton(NSMutableArray array,Button btn){
if (!String.IsNullOrEmpty(btn.Image?.File))
{
array.AddUtilityButton(btn.BorderColor.ToUIColor(), UIImage.FromBundle(btn.Image.File));
}
else
{
array.AddUtilityButton(btn.BorderColor.ToUIColor(), btn.Text);
}
}
public class CellDelegate : SWTableViewCellDelegate
{
SwipeCell forms_cell;
public CellDelegate(SwipeCell forms_cell)
{
this.forms_cell = forms_cell;
}
public override void DidTriggerLeftUtilityButton(SWTableViewCell cell, nint index)
{
if (forms_cell.LeftContextActions.Count > index)
{
var c = forms_cell.LeftContextActions[(int)index];
var cmd = c.Command;
if (cmd != null)
{
cmd.Execute(c.CommandParameter);
}
}
}
public override void DidTriggerRightUtilityButton(SWTableViewCell cell, nint index)
{
if (forms_cell.RightContextActions.Count > index)
{
var c = forms_cell.RightContextActions[(int)index];
var cmd = c.Command;
if (cmd != null)
{
cmd.Execute(c.CommandParameter);
}
}
}
}
Example XAML:
<ListView x:Name="SwipeList">
<ListView.ItemTemplate>
<DataTemplate>
<test:SwipeCell Text="{Binding Data}" ImageSource="{Binding Image}">
<test:SwipeViewCell.LeftContextActions>
<Button Text="L1" Command="{Binding LeftAction}" BorderColor="Aqua"/>
<Button Command="{Binding LeftAction2}" BorderColor="Gray" Image="xamarin.png"/>
</test:SwipeViewCell.LeftContextActions>
<test:SwipeViewCell.RightContextActions>
<Button Text="R1" Command="{Binding RightAction}" BorderColor="Blue" />
<Button Text="R2" Command="{Binding RightAction2}" BorderColor="Purple" />
</test:SwipeViewCell.RightContextActions>
</test:SwipeViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Example Code Behind
public class MyListItem
{
Page page;
public MyListItem(Page page)
{
this.page = page;
this.LeftAction= new Command(() => this.page.DisplayAlert("Left 1", this.Data, "OK"));
this.LeftAction2= new Command(() => this.page.DisplayAlert("Left 2", this.Data, "OK"));
this.RightAction= new Command(() => this.page.DisplayAlert("Right 1", this.Data, "OK"));
this.RightAction2= new Command(() => this.page.DisplayAlert("Right 2", this.Data, "OK"));
}
public string Image{ get; set; }
string data;
public string Data
{
get
{
return data;
}
set
{
data = value;
}
}
ICommand leftAction;
public ICommand LeftAction
{
get
{
return leftAction;
}
set
{
leftAction = value;
}
}
ICommand leftAction2;
public ICommand LeftAction2
{
get
{
return leftAction2;
}
set
{
leftAction2 = value;
}
}
ICommand rightAction;
public ICommand RightAction
{
get
{
return rightAction;
}
set
{
rightAction = value;
}
}
ICommand rightAction2;
public ICommand RightAction2
{
get
{
return rightAction2;
}
set
{
rightAction2 = value;
}
}
public override string ToString()
{
return this.Data;
}
}
public TestPage()
{
InitializeComponent();
this.SwipeList.ItemsSource = new List<MyListItem>(){
new MyListItem(this){Data="A"},
new MyListItem(this){Data="B", Image="xamarin.png"},
new MyListItem(this){Data="C"},
new MyListItem(this){Data="D"},
};
}
Context Actions wasn't exactly what my client wanted. The row menu didn't appear on swipe. It appeared when they hold tap on the row, and the menu appeared at the top of the screen.
I was able to accomplish the swipe row behaviour with the new Xamarin.Forms
SwipeView
Pass the current row into the CommandParameter, and use it in the event handler.
FYI: For some reason the SwipeView has a default BackgroundColor of white, which you can override with something else to match your theme.
Xaml:
<ListView Margin="-20,0,0,0" x:Name="photosListView" ItemSelected="OnItemSelected" VerticalOptions="FillAndExpand" SeparatorColor="Gray" VerticalScrollBarVisibility="Default" HasUnevenRows="true" SeparatorVisibility="Default" Background="{StaticResource PrimaryDark}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<SwipeView BackgroundColor="{StaticResource PrimaryDark}" >
<SwipeView.RightItems>
<SwipeItems>
<SwipeItem Text="Delete" BackgroundColor="LightPink" Clicked="OnDeleteRow" CommandParameter="{Binding .}" />
</SwipeItems>
</SwipeView.RightItems>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackLayout Orientation="Horizontal">
<CheckBox IsVisible="{Binding SelectEnabled}" Color="{StaticResource White}" IsChecked="{Binding Selected}" Margin="20,0,-15,0" CheckedChanged="OnItemCheckedChanged" />
<Grid WidthRequest="70" HeightRequest="50">
<Grid.Margin>
<OnPlatform x:TypeArguments="Thickness" Android="15,0,0,0" iOS="10,0,0,0" />
</Grid.Margin>
<Image Aspect="AspectFill" Source="{Binding ThumbImageSource}" HorizontalOptions="Fill" />
</Grid>
</StackLayout>
<StackLayout Grid.Column="1" Spacing="0" Padding="0" Margin="0,5,0,0">
<Label Text="{Binding Photo.Description}" TextColor="{StaticResource TextColour}" FontSize="16" FontAttributes="Bold" />
<Label Text="{Binding DateTakenString}" TextColor="{StaticResource TextColour}" FontSize="14" />
</StackLayout>
</Grid>
</SwipeView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
cs:
public async void OnDeleteRow(object sender, EventArgs e)
{
if (await GetDeleteRowConfirmationFromUser())
{
SwipeItem si = sender as SwipeItem;
PhotoListItem itemToDelete = si.CommandParameter as PhotoListItem;
LocalDatabaseService db = new LocalDatabaseService();
db.DeletePhoto(itemToDelete.Photo);
_listItems.Remove(itemToDelete);
}
}
i have an combox control defined with events in my mainpage.xaml
<Grid x:Name="LayoutRoot">
<ComboBox SelectionChanged="ComboBox_SelectionChanged"></ComboBox>
</Grid>
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
now how do we defined events for combox control in mvvm model .
and how do we bind the collection list to combo box. i am using SL 3
thanks
prince
In your xaml, you can bind the ItemSource and SelectedItem as shown below:
MainPage.xaml
<UserControl x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:App1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.DataContext>
<local:MainPage_ViewModel/>
</UserControl.DataContext>
<Grid x:Name="LayoutRoot" Background="White">
<ComboBox ItemsSource="{Binding MyItems}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" SelectionChanged="ComboBox_SelectionChanged" Height="30" Width="100"/>
</Grid>
In the MainPage.xaml.cs, your Selection changed method could just call the method on your ViewModel since you are using SL3:
MainPage.xaml.cs
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private MainPage_ViewModel viewModel
{
get { return this.DataContext as MainPage_ViewModel; }
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.viewModel.SelectionChanged();
}
}
Your ViewModel would have the MyItems collection and the SelectedItem to bind to:
MainPage_ViewModel.cs
public class MainPage_ViewModel : INotifyPropertyChanged
{
public ObservableCollection<string> MyItems
{
get { return myItems; }
set { myItems = value; }
}
private ObservableCollection<string> myItems = new ObservableCollection<string>() { "One", "Two", "Three" };
public string SelectedItem
{
get { return selectedItem; }
set { selectedItem = value; }
}
private string selectedItem = string.Empty;
public void SelectionChanged()
{
//Perform logic that needs to happen when selection changes
}
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Depending on what you were using your SelectionChanged method for, you may no longer need it since this would bind the SelectedItem to the ViewModel.
Hope this helps!