I am trying to create a Xamarin forms content page that contains a grid with an entry form, and then on the same page, a data grid containing the linked data. So I have a surgical case and then the data grid will contain staff linked to that surgical case. I am not sure how to link the staff data grid to the surgical case so that it only shows the staff from that one case. I am including all of this in the same viewmodel. How do I pass the SxCaseId from the entry form to the datagrid?
public class SxCaseMasterViewModel : ViewModelBase
{
private ISxCaseDataService _sxCaseDataService;
private ICaseStaffJoinForSxCaseDataService _caseStaffJoinForSxCaseDataService;
private SxCase _selectedSxCase;
private CaseStaffJoin _selectedCaseStaffJoin;
private CaseStaffJoin caseStaffJoin;
private ObservableCollection<CaseStaffJoin> _caseStaffJoins;
private ObservableCollection<SxCase> _sxCases;
public SxCaseMasterViewModel(IConnectionService connectionService,
INavigationService navigationService, IDialogService dialogService,
ICaseStaffJoinForSxCaseDataService caseStaffJoinForSxCaseDataService,
ISxCaseDataService sxCaseDataService) : base(connectionService, navigationService, dialogService)
{
_sxCaseDataService = sxCaseDataService;
_caseStaffJoinForSxCaseDataService = caseStaffJoinForSxCaseDataService;
SxCases = new ObservableCollection<SxCase>();
CaseStaffJoins = new ObservableCollection<CaseStaffJoin>();
}
public ICommand UpdateSxCaseCommand => new Command(OnUpdateSxCase);
public SxCase SelectedSxCase
{
get => _selectedSxCase;
set
{
_selectedSxCase = value;
OnPropertyChanged();
}
}
public ObservableCollection<SxCase> SxCases
{
get => _sxCases;
set
{
_sxCases = value;
OnPropertyChanged();
}
}
public override async Task InitializeAsync(object sxCase)
{
SelectedSxCase = (SxCase)sxCase;
}
public CaseStaffJoin SelectedCaseStaffJoin
{
get => _selectedCaseStaffJoin;
set
{
_selectedCaseStaffJoin = value;
OnPropertyChanged();
}
}
public ObservableCollection<CaseStaffJoin> CaseStaffJoins
{
get => _caseStaffJoins;
set
{
_caseStaffJoins = value;
OnPropertyChanged();
}
}
private async void OnUpdateSxCase(object sxCase)
{
await _sxCaseDataService.UpdateSxCase(SelectedSxCase.SxCaseId, SelectedSxCase);
OnPropertyChanged();
await _dialogService.ShowDialog("Case details updated.", "Success", "OK");
await _navigationService.NavigateToAsync<SxCaseViewModel>();
//await _navigationService.PopToRootAsync();
}
public ICommand DeleteSxCaseCommand => new Command(async () =>
{
await _sxCaseDataService.DeleteSxCase(SelectedSxCase.SxCaseId);
await _dialogService.ShowDialog("Case deleted.", "Success", "OK");
await _navigationService.NavigateToAsync<SxCaseViewModel>();
});
}
<ContentPage.Content>
<Grid>
<StackLayout BackgroundColor="Yellow">
<Grid Grid.Row="0" Padding="10" x:Name="MasterGrid">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="CaseId" Grid.Row="0" Grid.Column="0"/>
<Label Text="{Binding SelectedSxCase.SxCaseId}" Grid.Row="0" Grid.Column="1"/>
<Label Text="Dos" Grid.Row="1" Grid.Column="0"/>
<renderers:SfDatePicker x:Name="dos" BindingContext="{Binding SelectedSxCase.Dos}" Grid.Row="1" Grid.Column="1" HorizontalOptions="StartAndExpand"/>
<Label Text="EyeId" Grid.Column="0" Grid.Row="2"/>
<Entry Text="{Binding SelectedSxCase.EyeId, Mode=TwoWay}" Grid.Column="1" Grid.Row="2"/>
<Label Text="Facesheet" Grid.Column="0" Grid.Row="3"/>
<Entry Text="{Binding SelectedSxCase.Facesheet, Mode=TwoWay}" Grid.Column="1" Grid.Row="3"/>
<Label Text="Record" Grid.Column="0" Grid.Row="4"/>
<Entry Text="{Binding SelectedSxCase.Record, Mode=TwoWay}" Grid.Column="1" Grid.Row="4"/>
<Label Text="Complication" Grid.Column="0" Grid.Row="5"/>
<Switch IsToggled="{Binding SelectedSxCase.Complication, Mode=TwoWay}" Grid.Column="1" Grid.Row="5"/>
<Label Text="ReturnOr" Grid.Column="0" Grid.Row="6"/>
<Switch IsToggled="{Binding SelectedSxCase.ReturnOr, Mode=TwoWay}" Grid.Column="1" Grid.Row="6"/>
<Label Text="PhysicianId" Grid.Column="0" Grid.Row="7"/>
<Entry Text="{Binding SelectedSxCase.PhysicianId, Mode=TwoWay}" Grid.Column="1" Grid.Row="7"/>
<Label Text="{Binding SelectedSxCase.Physician}"/>
<Button Text="Update Case" Style="{StaticResource RegularButton}"
Command="{Binding UpdateSxCaseCommand}" Grid.Row="8" Grid.Column="0" Grid.ColumnSpan="2"
HorizontalOptions="Center"/>
<Button Text="Delete Case" Style="{StaticResource RegularButton}"
Command="{Binding DeleteSxCaseCommand}" Grid.Row="8" Grid.Column="1" Grid.ColumnSpan="2"
HorizontalOptions="Center"/>
</Grid>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="5*" x:Name="firstRow" />
<RowDefinition Height="3*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<datagrid:SfDataGrid
ItemsSource="{Binding CaseStaffJoins, Mode=TwoWay}" AllowEditing="True" AutoGenerateColumns="True">
</datagrid:SfDataGrid>
</Grid>
</StackLayout>
</Grid>
</ContentPage.Content>
Related
Firstscreen with all the notes.
After I deleted the first note!
I have recently started programming with .NET MAUI. The elements are correctly removed in the C# list. However, after deleting the remaining elements are only partially displayed. That means that only e.g. the 4th element is displayed. For the other elements only an empty bar is displayed.
My code so far:
XAML:
<VerticalStackLayout>
<ScrollView>
<StackLayout>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
Source="logo.png"
WidthRequest="150"
HorizontalOptions="Start"
VerticalOptions="Start"/>
<Label
TextColor="Black"
Grid.Column="1"
Text="TODO"
FontSize="35"
HorizontalOptions="Start"
VerticalOptions="Start"
Margin="23"/>
</Grid>
<Grid BackgroundColor="#24D4A3">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListView
Grid.ColumnSpan="2"
Grid.RowSpan="2"
RowHeight="100"
x:Name="listview">
<ListView.ItemTemplate>
<DataTemplate >
<ViewCell >
<Grid BackgroundColor="#24D4A3">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Button BackgroundColor="#DEABF5"
Text="{Binding Title}"
Clicked="onNoteSelected"
BorderWidth="2"
TextColor="Black"
FontSize="28"
Margin="20"
CornerRadius="100"
WidthRequest="350"
HeightRequest="70"
HorizontalOptions="Center"
VerticalOptions="Start"/>
<Button
BindingContext="{Binding Id}"
Clicked="ToDoSolved"
BorderWidth="2"
BorderColor="Black"
BackgroundColor="White"
WidthRequest="45"
HeightRequest="45"
CornerRadius="35"
Margin="0,0,260,0"
/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ImageButton
Clicked="Settings"
Source="settings.png"
Grid.Row="0"
Grid.Column="2"
BorderColor="#2b3c3c"
BorderWidth="0"
BackgroundColor="#34A4EB"
CornerRadius="35"
HorizontalOptions="End"
WidthRequest="70"
HeightRequest="70"
Margin="0,10, 10, 0"
VerticalOptions="Start"/>
<ImageButton
Clicked="CreateNote"
Source="add.png"
Grid.Row="1"
Grid.Column="2"
BorderColor="#2b3c3c"
BorderWidth="0"
BackgroundColor="#34A4EB"
CornerRadius="35"
HorizontalOptions="End"
WidthRequest="70"
HeightRequest="70"
Margin="0,0,10,10"
Padding="2,0,0,0"/>
</Grid>
</StackLayout>
</ScrollView>
</VerticalStackLayout>
C#:
public partial class MainPage : ContentPage
{
private ObservableCollection<Note> notes = new ObservableCollection<Note>();
public ObservableCollection<Note> Notes
{
get { return notes; }
set { notes = value; }
}
public MainPage()
{
InitializeComponent();
notes.Add(new Note(1, "My Note1", "I'm ugly"));
notes.Add(new Note(2, "My Note2", "I'm short"));
notes.Add(new Note(3, "My Note3", "I'm smart"));
notes.Add(new Note(4, "My Note4", "I'm smart"));
//notes.Add(new Note(6, "My Note6", "I'm smart"));
//notes.Add(new Note(7, "My Note7", "I'm smart"));
//notes.Add(new Note(8, "My Note8", "I'm smart"));
//notes.Add(new Note(9, "My Note9", "I'm smart"));
this.BindingContext= Notes;
listview.ItemsSource= Notes;
}
private async void CreateNote(object sender, EventArgs e)
{
await Shell.Current.GoToAsync("//CreateNote");
}
private async void Settings(object sender, EventArgs e)
{
await Shell.Current.GoToAsync("//Settings");
}
private void ToDoSolved(object sender, EventArgs e)
{
Button button= (Button) sender ;
var id = (int)button.BindingContext;
var item = Notes.SingleOrDefault(x => x.Id == id);
if (item != null)
{
Notes.Remove(item);
Console.WriteLine(id);
}
}
async void onNoteSelected(object sender, EventArgs e)
{
Button button= (Button) sender ;
var id = (int)button.BindingContext;
//await Shell.Current.GoToAsync("NotePage" + id);
}
}
I would be grateful for any help :)
To delete the item, since you are using ListView, you can delete the via
Button click. However, you need to delete the item from bottom to top in order.
Code-behind:
public partial class MainPage : ContentPage
{
public ObservableCollection<Note> Notes { get; private set; } = new ObservableCollection<Note>();
public MainPage()
{
InitializeComponent();
AddNotes();
BindingContext = this;
}
private void AddNotes()
{
Notes.Add(new Note("0", "My Note1"));
Notes.Add(new Note("1", "My Note2"));
Notes.Add(new Note("2", "My Note3"));
Notes.Add(new Note("3", "My Note4"));
}
private void Button_Clicked(object sender, EventArgs e)
{
var note = (Button)sender;
Note listnote = (from itm in Notes
where itm.Id == note.CommandParameter.ToString()
select itm).FirstOrDefault<Note>();
Notes.Remove(listnote);
}
}
Xaml:
<VerticalStackLayout>
<ScrollView>
<StackLayout>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
Source="logo.png"
WidthRequest="150"
HorizontalOptions="Start"
VerticalOptions="Start"
/>
<Label
TextColor="Black"
Grid.Column="1"
Text="TODO"
FontSize="35"
HorizontalOptions="Start"
VerticalOptions="Start"
Margin="23"
/>
</Grid>
<Grid BackgroundColor="#24D4A3">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListView
Grid.ColumnSpan="2"
Grid.RowSpan="2"
RowHeight="100"
x:Name="listview"
ItemsSource="{Binding Notes}" >
<ListView.ItemTemplate>
<DataTemplate >
<ViewCell>
<Grid BackgroundColor="#24D4A3" >
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Button BackgroundColor="#DEABF5"
Text="{Binding Title}"
BorderWidth="2"
TextColor="Black"
FontSize="28"
Margin="20"
CornerRadius="100"
WidthRequest="350"
HeightRequest="70"
HorizontalOptions="Center"
VerticalOptions="Start"/>
<Button
Text="Delete"
Clicked="Button_Clicked"
CommandParameter="{Binding Id}"
BorderWidth="2"
BorderColor="Black"
BackgroundColor="White"
WidthRequest="45"
HeightRequest="45"
CornerRadius="35"
Margin="0,0,260,0"
/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</StackLayout>
</ScrollView>
</VerticalStackLayout>
Note:
public class Note
{
public string Id { get; set; }
public string Title { get; set; }
public Note(string id, string title)
{
Id = id;
Title = title;
}
}
I am trying to bind properties of views in the view page to a class that I have in a carpet called ViewModel, and then from an instance of another class called Category (a model) in a carpet called Model I am trying to access to properties contained there, the problem is that it does not seem to work .Although there are no error codes in the codes, I cannot access the bindings when I run the application. The warning I get is:
Datacontext not found for binding SelectedCategory .CategoryName(I get the same warning in ProductItemByCategory binding)
Do you have any solution suggestions?
Thank You!!
I will explain it with more details in the code:
1.CategoryView.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pancake="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView"
x:Class="DirencNetClone.Views.CategoryView">
<ContentPage.Content>
<ScrollView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row="1" Text="{Binding SelectedCategory.CategoryName}" FontSize="Body" Margin="25,-85,0,0" TextColor="Black" />
<ImageButton Source="logo.png" Grid.Row="0" HorizontalOptions="Start" Aspect="AspectFill" VerticalOptions="Start" Margin="10,30" Clicked="ImageButton_Clicked"/>
<pancake:PancakeView Grid.Row="2" BackgroundColor="Wheat" Margin="0,40">
<Grid Padding="25,30" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="{Binding TotalProductItems,StringFormat= '{0} Total Items'}" FontAttributes="Bold" FontSize="10" TextColor="Black"/>
<Image Grid.Row="0" Grid.Column="1" Source="info.png"/>
<CollectionView ItemsSource="{Binding ProductItemsByCategory}"
VerticalOptions="Start"
VerticalScrollBarVisibility="Never"
Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
SelectionMode="Single"
SelectionChanged="CollectionView_SelectionChanged">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="False" BackgroundColor="White" HeightRequest="90" Margin="0,10">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<pancake:PancakeView Grid.Column="0" Grid.Row="0" Grid.RowSpan="3" Margin="0,0,10,0 " >
<Image Source="{Binding ImageUrl}" HeightRequest="100" WidthRequest="95" Aspect="AspectFill"/>
</pancake:PancakeView>
<Label Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding Name}" FontSize="15" TextColor="Black"/>
<Label Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding Description}" FontSize="15" TextColor="Black"/>
<Label Grid.Row="2 " Grid.Column="1" Margin="30,0,0,0" VerticalOptions="Center" FontSize="15" >
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding Rating}" FontAttributes="Bold" />
<Span Text="{Binding RatingDetail} " TextColor="Yellow"/>
</FormattedString>
</Label.FormattedText>
</Label>
<Image Grid.Row="0" Grid.Column="2" Source="{Binding HomeSelected}" HeightRequest="15"/>
<Label Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding Price}" FontSize="15" TextColor="Black"/>
</Grid>
</Frame>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</pancake:PancakeView>
</Grid>
</ScrollView>
</ContentPage.Content>
2.CategoryViewModel.cs
public class CategoryViewModel:BaseViewModel
{
private Category _SelectedCategory;
public Category SelectedCategory
{
set
{
_SelectedCategory = value;
OnPropertyChanged();
}
get
{
return _SelectedCategory;
}
}
public ObservableCollection<ProductItem> ProductItemsByCategory { get; set; }
private int _TotalProductItems;
public int TotalProductItems
{
set
{
this._TotalProductItems = value;
OnPropertyChanged();
}
get
{
return this._TotalProductItems;
}
}
public CategoryViewModel( Category category)
{
SelectedCategory = category;
ProductItemsByCategory = new ObservableCollection<ProductItem>();
GetProductItems(category.CategoryID);
}
async void GetProductItems(int categoryID)
{
var data = await new ProductItemService().GetProductItemsByCategoryAsync(categoryID);
ProductItemsByCategory.Clear();
foreach (var item in data)
{
ProductItemsByCategory.Add(item);
}
TotalProductItems = ProductItemsByCategory.Count;
}
}
3.Category.cs(Model)
public class Category
{
public int CategoryID { get; set; }
public string ImageUrl { get; set; }
public string CategoryName { get; set; }
}
4.CategoryView.cs
public partial class CategoryView : ContentPage
{
CategoryViewModel cvm;
public CategoryView(Category category )
{
InitializeComponent();
cvm = new CategoryViewModel(category);
this.BindingContext=cvm
;
}
async void ImageButton_Clicked(object sender, EventArgs e)
{
await Navigation.PopModalAsync();
}
async void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var selectedProduct = e.CurrentSelection.FirstOrDefault() as ProductItem;
if (selectedProduct == null)
return;
await Navigation.PushModalAsync(new ProductsDetailsView(selectedProduct));
((CollectionView)sender).SelectedItem = null;
}
}
5.BaseViewModel
public class BaseViewModel: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string name = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
6.ProductItem(Model)
public class ProductItem
{
public int ProductID { get; set; }
public int CategoryID { get; set; }
public string Rating { get; set;
}
public string Description { get; set;
}
public string RatingDetail { get; set; }
public string HomeSelected { get; set; }
public string ImageUrl { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
7.ProductView.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DirencNetClone.Views.ProductsView"
xmlns:vm="clr-namespace:DirencNetClone.ViewModels"
xmlns:pancake ="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView"
>
<ContentPage.BindingContext>
<vm:ProductsViewModel/>
</ContentPage.BindingContext>
<ContentPage.Content>
<Grid Margin="20,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Image Source="logo.png " Grid.Row="0" Grid.Column="0" HorizontalOptions="Center"/>
<Label Text="{Binding UserEmail} " Grid.Row="1" Grid.Column="0" FontSize="Body"/>
<ImageButton Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Source="ic_menu_categories.png" Margin="0,0,10,0" HorizontalOptions="End"/>
<Label Text="{Binding UserCartItemsCount}" FontSize="Subtitle" Grid.Row="0" Grid.Column="2" Grid.RowSpan="2" HorizontalTextAlignment="End" VerticalTextAlignment="Start"/>
<ImageButton Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Source="ic_menu_basket.png" Margin="0,0,10,0" HorizontalOptions="Center"
Command="{Binding ViewCartCommand } "/>
<ImageButton Grid.Row="0" Grid.Column="3" Grid.RowSpan="2" Source="ic_menu_profile.png" Margin="0,0,10,0" HorizontalOptions="End" Command="{Binding LogoutCommand}"/>
</Grid>
<Grid Grid.Row="1" Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<SearchBar Grid.Column="0" Placeholder="Ürün Ara" BackgroundColor="Transparent" HorizontalOptions="Fill"/>
</Grid>
<CollectionView ItemsSource="{Binding Categories} "
Margin="0,20"
HeightRequest="125"
VerticalOptions="FillAndExpand"
HorizontalScrollBarVisibility="Never"
ItemsLayout="HorizontalList"
SelectionChanged="CollectionView_SelectionChanged"
SelectionMode="Single"
Grid.Row="2">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HeightRequest="50" HasShadow="False" BackgroundColor="White" CornerRadius="10">
<Image Source="{Binding ImageUrl}"/>
</Frame>
<Label Text="{Binding CategoryName} " HorizontalTextAlignment="Center"/>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Label Grid.Row="3" Text="Latest Items" FontSize="25" FontAttributes="Bold"/>
<CollectionView ItemsSource="{Binding LatestItems}" Margin="0,20,10,0" VerticalOptions="Start" VerticalScrollBarVisibility="Never" Grid.Row="4">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto "/>
</Grid.RowDefinitions>
<pancake:PancakeView Grid.Row="0" Margin="0,0,10,0">
<Image Source="{Binding ImageUrl}" HeightRequest="220" Aspect="Fill"/>
</pancake:PancakeView>
<Frame Grid.Row="1" Margin="20,-80,20,70" BackgroundColor="Wheat" HorizontalOptions="End">
<Label Text="{Binding Price,StringFormat='{0:c}'}" FontSize="Medium" FontAttributes="Bold" TextColor="Black" HeightRequest="10"/>
</Frame>
<Label Grid.Row="1" Text="{Binding Name}" FontSize=" 22" FontAttributes="Bold" VerticalTextAlignment="Center" />
<Label Grid.Row="2" Margin="30,0,0,0" FontSize="15" VerticalOptions="Center" >
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding Rating}" FontAttributes="Bold"/>
<Span Text="{Binding Description}" TextColor="White"/>
</FormattedString>
</Label.FormattedText>
</Label>
</Grid>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage.Content>
**8.ProductViewModel**
public class ProductsViewModel :BaseViewModel
{
private string _UserEMail;
public string UserEmail
{
set
{
this._UserEMail = value;
OnPropertyChanged();
}
get
{
return this._UserEMail;
}
}
public ObservableCollection<Category> Categories { get; set; }
public ObservableCollection<ProductItem> LatestItems { get; set; }
private int _UserCartItemsCount;
public int UserCartItemsCount
{
set
{
this._UserCartItemsCount = value;
OnPropertyChanged();
}
get
{
return this._UserCartItemsCount;
}
}
public Command ViewCartCommand { get; set; }
public Command LogoutCommand
{
get; set;
}
public ProductsViewModel()
{
var uemail = Preferences.Get("UserEmail", String.Empty);
if (String.IsNullOrEmpty(uemail))
UserEmail = "Guest";
else
UserEmail = uemail;
UserCartItemsCount = new CartItemService().GetUserCartCount();
Categories = new ObservableCollection<Category>();
LatestItems = new ObservableCollection<ProductItem>();
GetCategories();
GetLatestItems();
ViewCartCommand = new Command(async () => ViewCartAsync());
LogoutCommand = new Command(async () => await LogoutAsync());
}
async void GetLatestItems()
{
var data = await new ProductItemService().GetLatestProductItemsAsync();
LatestItems.Clear();
foreach(var item in data)
{
LatestItems.Add(item);
}
}
private async Task LogoutAsync()
{
await Application.Current.MainPage.Navigation.PushModalAsync(new LogoutVew());
}
private async void GetCategories()
{
var data = await new CategoryDataService().GetCategoriesAsync();
Categories.Clear();
foreach (var item in data)
{
Categories.Add(item);
}
}
private async Task ViewCartAsync()
{
await Application.Current.MainPage.Navigation.PushModalAsync(new CartView());
}
I need to databind a class object to a custom ViewCell. I used the {Binding propName} for the fields on the controls inside the ViewCell. I'm not sure if I am adding the ViewCell correctly since it shows as [AppName.GridView] and does not show the control I built. What is the correct way to bind this control with the custom class?
<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
Height="50">
<Frame HeightRequest="50" Padding="0" Margin="1" BorderColor="blue" CornerRadius="4" BackgroundColor="lightBlue">
<Grid BindingContext="Binding local:di" >
<Grid.RowDefinitions >
<RowDefinition Height="34"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" BackgroundColor="Transparent" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3"/>
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="5*" />
<ColumnDefinition Width="5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions >
<RowDefinition Height="40"></RowDefinition>
</Grid.RowDefinitions>
<Button x:Name="btnItem" Text="{Binding itemName}" Clicked="BtnClicked" Padding="0" Grid.Column="1" FontSize="20" />
<Label x:Name="lbAmt" Text="{Binding amt}" Grid.Column="2" Margin="2" VerticalTextAlignment="Center" HorizontalTextAlignment="End" FontSize="20" BackgroundColor="lightBlue" />
<Label x:Name="lbType" Text="{Binding amtType}" Grid.Column="3" Margin="2" VerticalTextAlignment="Center" FontSize="20" BackgroundColor="lightBlue" />
</Grid>
...
</Grid>
</Frame>
The code to add the object.
DItem di = new DItem() { itemName = "someName", amt = 1, amtType = xf };
GridItems gi = new GridItems() { di = di };
ObservableCollection<GridItems> lv = new ObservableCollection<GridItems>();
lv.Add(gi);
lvItems.ItemsSource = lv;
If you want to achieve the databinding with listview(MVVM),
Here is running screenshot.
First of all, you can create a model DItem.I achieve the INotifyPropertyChanged interface, layout will changed when the value was changed
public class DItem: INotifyPropertyChanged
{
string _itemName;
public string itemName
{
set
{
if (_itemName != value)
{
_itemName = value;
OnPropertyChanged("itemName");
}
}
get
{
return _itemName;
}
}
int _amt;
public int amt
{
set
{
if (_amt != value)
{
_amt = value;
OnPropertyChanged("amt");
}
}
get
{
return _amt;
}
}
string _amtType;
public string amtType
{
set
{
if (_amtType != value)
{
_amtType = value;
OnPropertyChanged("amtType");
}
}
get
{
return _amtType;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Then, achieve the ModelView.DItemViewModel, We do not need create GridItems just add the DItem to the ObservableCollection<DItem>
public class DItemViewModel
{
public ObservableCollection<DItem> lv { get; set; }
public DItemViewModel()
{
DItem di = new DItem() { itemName = "someName", amt = 1, amtType = "xf" };
lv = new ObservableCollection<DItem>();
lv.Add(di);
}
}
Here is layout of listview. add the ItemsSource="{Binding lv}" for listview.
<ListView ItemsSource="{Binding lv}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame HeightRequest="50" Padding="0" Margin="1" BorderColor="blue" CornerRadius="4" BackgroundColor="lightBlue">
<Grid >
<Grid.RowDefinitions >
<RowDefinition Height="34"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" BackgroundColor="Transparent" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3"/>
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="5*" />
<ColumnDefinition Width="5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions >
<RowDefinition Height="40"></RowDefinition>
</Grid.RowDefinitions>
<Button x:Name="btnItem" Text="{Binding itemName}" Clicked="btnItem_Clicked" Padding="0" Grid.Column="1" FontSize="20" />
<Label x:Name="lbAmt" Text="{Binding amt}" Grid.Column="2" Margin="2" VerticalTextAlignment="Center" HorizontalTextAlignment="End" FontSize="20" BackgroundColor="lightBlue" />
<Label x:Name="lbType" Text="{Binding amtType}" Grid.Column="3" Margin="2" VerticalTextAlignment="Center" FontSize="20" BackgroundColor="lightBlue" />
</Grid>
</Grid>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And here is background code for the listview.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new DItemViewModel();
}
private void btnItem_Clicked(object sender, EventArgs e)
{
}
}
Here are helpful articles about MVVM in Xamarin forms.
https://almirvuk.blogspot.com/2017/02/xamarinforms-listview-simple-mvvm.html
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/data-bindings-to-mvvm
Try to create simple app that will add items to the list. Have problems with binding entries with properties in ViewModel.
Here is my xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModels="clr-namespace:MyScoreDemo.ViewModels;assembly=MyScoreDemo"
x:Class="MyScoreDemo.Views.ClubListPage">
<StackLayout
Padding="15"
Spacing="10">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="Name:" Grid.Row="0" Grid.Column="0"/>
<Entry x:Name="EntryName" Text="{Binding Club.Name, Mode=OneWayToSource}" Grid.Row="0" Grid.Column="1"/>
<Label Text="Country:" Grid.Row="1" Grid.Column="0"/>
<Entry x:Name="EntryCountry" Text="{Binding Club.Country, Mode=OneWayToSource}" Grid.Row="1" Grid.Column="1"/>
<Button Text="Add" Command="{Binding AddCommand}" CommandParameter="{x:Reference EntryName}"
Grid.Row="2" Grid.ColumnSpan="2" Grid.Column="0" />
</Grid>
<ListView ItemsSource="{Binding Clubs}"
Margin="5">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding Path=Name}"/>
<Label Text="{Binding Path=Country}" Grid.Column="1"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackLayout.BindingContext>
<viewModels:ClubListViewModel/>
</StackLayout.BindingContext>
</StackLayout>
And ViewModel code:
private Club _club;
public ICommand AddCommand { get; set; }
public ICommand RemoveCommand { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<Club> Clubs { get; set; }
public ClubListViewModel()
{
AddCommand = new Command(AddClub);
RemoveCommand = new Command(RemoveClub);
Clubs = new ObservableCollection<Club>();
}
public Club Club
{
get => _club;
set
{
_club = value;
OnPropertyChanged("Club");
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
//Commands
private void AddClub()
{
}
Set breakpoints in property`s Club set section and try different modes, but it never stops.
All that I need to change is ta add Club = new Club(); in constructor of my ViewModel class.
I'm building an application which will be very similar to the know game "Game of Life" I'm not very experienced with wither C# xaml or wpf of the time being but i believe this will be a good way to learn it all better. Thus there will be struggles on the way.
I have made a 10x10 grid an filed it with buttons and each button have there place in the grid. To keep track of each generation i amuse i have to keep track the buttons position in the grid. So i thought, if i can use each buttons grid position Y-axis & X-axis. It would not be to hard to make simple method to irritate thorough each button and compare the positions within two foor loops, one for each axis.
I've tried to revive a buttons grid position with biding but i have not manage to get it working.
If it's possible to get a buttons grid potion from a grid, how do i do?
Is the a better way to approach my goal for the sake of good practice?
--
Code behind.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using GOL.GameGrid;
using GOL.GameGrid.Props;
namespace GOL
{
/// <summary>
/// Interaction logic for frmGame.xaml
/// </summary>
public partial class frmGame : Window
{
string HelloWorld = "Hello World";
private string btnDataContext;
public frmGame()
{
InitializeComponent();
MyBtnProps btnContent = new MyBtnProps() { Name = "T" };
btnCollection();
}
private void btnReturn_Click(object sender, RoutedEventArgs e)
{
var newW = new MainWindow();
newW.Show();
this.Close();
}
private void btnCollection()
{
MyBtnProps btnDataContext = new MyBtnProps() { IsAlive = "T" };
//btn00.DataContext = btnDataContext;
var btnCollection = new List<Button>();
#region Grid Buttons added to collection.
btnCollection.Add(btn01);
btnCollection.Add(btn01);
btnCollection.Add(btn02);
btnCollection.Add(btn03);
btnCollection.Add(btn04);
btnCollection.Add(btn05);
btnCollection.Add(btn06);
btnCollection.Add(btn07);
btnCollection.Add(btn08);
btnCollection.Add(btn09);
btnCollection.Add(btn10);
btnCollection.Add(btn11);
btnCollection.Add(btn12);
btnCollection.Add(btn13);
btnCollection.Add(btn14);
btnCollection.Add(btn15);
btnCollection.Add(btn16);
btnCollection.Add(btn17);
btnCollection.Add(btn18);
btnCollection.Add(btn19);
btnCollection.Add(btn20);
btnCollection.Add(btn21);
btnCollection.Add(btn22);
btnCollection.Add(btn23);
btnCollection.Add(btn24);
btnCollection.Add(btn25);
btnCollection.Add(btn26);
btnCollection.Add(btn27);
btnCollection.Add(btn28);
btnCollection.Add(btn29);
btnCollection.Add(btn30);
btnCollection.Add(btn31);
btnCollection.Add(btn32);
btnCollection.Add(btn33);
btnCollection.Add(btn34);
btnCollection.Add(btn35);
btnCollection.Add(btn36);
btnCollection.Add(btn37);
btnCollection.Add(btn38);
btnCollection.Add(btn39);
btnCollection.Add(btn40);
btnCollection.Add(btn41);
btnCollection.Add(btn42);
btnCollection.Add(btn43);
btnCollection.Add(btn44);
btnCollection.Add(btn45);
btnCollection.Add(btn46);
btnCollection.Add(btn47);
btnCollection.Add(btn48);
btnCollection.Add(btn49);
btnCollection.Add(btn50);
btnCollection.Add(btn51);
btnCollection.Add(btn52);
btnCollection.Add(btn53);
btnCollection.Add(btn54);
btnCollection.Add(btn55);
btnCollection.Add(btn56);
btnCollection.Add(btn57);
btnCollection.Add(btn58);
btnCollection.Add(btn59);
btnCollection.Add(btn60);
btnCollection.Add(btn61);
btnCollection.Add(btn62);
btnCollection.Add(btn63);
btnCollection.Add(btn64);
btnCollection.Add(btn65);
btnCollection.Add(btn66);
btnCollection.Add(btn67);
btnCollection.Add(btn68);
btnCollection.Add(btn69);
btnCollection.Add(btn70);
btnCollection.Add(btn71);
btnCollection.Add(btn72);
btnCollection.Add(btn73);
btnCollection.Add(btn74);
btnCollection.Add(btn75);
btnCollection.Add(btn76);
btnCollection.Add(btn77);
btnCollection.Add(btn78);
btnCollection.Add(btn79);
btnCollection.Add(btn80);
btnCollection.Add(btn81);
btnCollection.Add(btn82);
btnCollection.Add(btn83);
btnCollection.Add(btn84);
btnCollection.Add(btn85);
btnCollection.Add(btn86);
btnCollection.Add(btn87);
btnCollection.Add(btn88);
btnCollection.Add(btn89);
btnCollection.Add(btn90);
btnCollection.Add(btn91);
btnCollection.Add(btn92);
btnCollection.Add(btn93);
btnCollection.Add(btn94);
btnCollection.Add(btn95);
btnCollection.Add(btn96);
btnCollection.Add(btn97);
btnCollection.Add(btn98);
btnCollection.Add(btn99);
#endregion Buttons added to collection.
foreach (var item in btnCollection)
{
item.DataContext = btnDataContext;
btn01.Background = new SolidColorBrush(Color.FromArgb(100, 102, 255, 179));
btn00.Background = Brushes.Cornsilk;
if (btn00.Background == Brushes.Cornsilk)
{
btn01.Background = Brushes.Azure;
}
else
{
btn01.Background = new SolidColorBrush(Color.FromArgb(100, 102, 120, 255));
}
}
}
#region LeftBtnClickEvents
private void btn00_Click(object sender, RoutedEventArgs e)
{
btn00.Background = Brushes.Green;
}
private void btn01_Click(object sender, RoutedEventArgs e)
{
btn01.Background = Brushes.Green;
}
private void btn02_Click(object sender, RoutedEventArgs e)
{
btn02.Background = Brushes.Green;
}
private void btn03_Click(object sender, RoutedEventArgs e)
{
btn03.Background = Brushes.Green;
}
private void btn04_Click(object sender, RoutedEventArgs e)
{
btn04.Background = Brushes.Green;
}
private void btn05_Click(object sender, RoutedEventArgs e)
{
btn05.Background = Brushes.Green;
}
private void btn06_Click(object sender, RoutedEventArgs e)
{
btn60.Background = Brushes.Green;
}
private void btn07_Click(object sender, RoutedEventArgs e)
{
btn07.Background = Brushes.Green;
}
private void btn08_Click(object sender, RoutedEventArgs e)
{
btn08.Background = Brushes.Green;
}
private void btn09_Click(object sender, RoutedEventArgs e)
{
btn09.Background = Brushes.Green;
}
#endregion LeftBtnClickEvents
#region RightBtnClickEvent
private void btn00_RightClick(object sender, MouseButtonEventArgs e)
{
btn00.Background = Brushes.Red;
}
private void btn01_RightClick(object sender, MouseButtonEventArgs e)
{
btn01.Background = Brushes.Red;
}
private void btn02_RightClick(object sender, MouseButtonEventArgs e)
{
btn02.Background = Brushes.Red;
}
private void btn03_RightClick(object sender, MouseButtonEventArgs e)
{
btn03.Background = Brushes.Red;
}
private void btn04_RightClick(object sender, MouseButtonEventArgs e)
{
btn04.Background = Brushes.Red;
}
private void btn05_RightClick(object sender, MouseButtonEventArgs e)
{
btn05.Background = Brushes.Red;
}
private void btn06_RightClick(object sender, MouseButtonEventArgs e)
{
btn06.Background = Brushes.Red;
}
private void btn07_RightClick(object sender, MouseButtonEventArgs e)
{
btn07.Background = Brushes.Red;
}
private void btn08_RightClick(object sender, MouseButtonEventArgs e)
{
btn08.Background = Brushes.Red;
}
private void btn09_RightClick(object sender, MouseButtonEventArgs e)
{
btn09.Background = Brushes.Red;
}
#endregion RightBtnClickEvent
}
}
--
xaml code.
<Window x:Class="GOL.frmGame"
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:GOL"
mc:Ignorable="d"
Title="frmGame" Height="326.4" Width="388.2" Background="#f2f2f2">
<Grid x:Name="WindowGrid" Height="Auto" Width="Auto">
<Grid x:Name="btnNavbar" HorizontalAlignment="Left" Height="38" Margin="40,241,0,0" VerticalAlignment="Top" Width="300">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Button x:Name="btnNewGen" Content="New Generation" Width="Auto" Height="Auto" Grid.Column="0" Grid.Row="0"/>
<Button x:Name="btnLoadGen" Content="Load Generation" Width="Auto" Height="Auto" Grid.Column="0" Grid.Row="1"/>
<Button x:Name="btnPlayGen" Content="PLAY" Width="Auto" Height="Auto" Grid.Column="1" Grid.Row="0"/>
<Button x:Name="button1" Content="Magic" Width="Auto" Height="Auto" Grid.Column="1" Grid.Row="2"/>
<Button x:Name="btnSave" Content="Save" Width="Auto" Height="Auto" Grid.Column="3" Grid.Row="0"/>
<Button x:Name="btnReturn" Content="Menu" Width="Auto" Height="Auto" Grid.Column="3" Grid.Row="1"/>
</Grid>
<Grid x:Name="GameBoard" HorizontalAlignment="Left" Height="200" Margin="80,20,0,0" VerticalAlignment="Top" Width="200" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Button x:Name="btn00" Content="" Grid.Column="0" Grid.Row="0" Height="Auto" Width="Auto" Click="btn00_Click" MouseRightButtonUp="btn00_RightClick" DataContext="{Binding IsAlive}"/>
<Button x:Name="btn01" Content="" Grid.Column="0" Grid.Row="1" Height="Auto" Width="Auto" Click="btn01_Click" MouseRightButtonUp="btn01_RightClick" DataContext="{Binding IsAlive}"/>
<Button x:Name="btn02" Content="" Grid.Column="0" Grid.Row="2" Height="Auto" Width="Auto" Click="btn02_Click" MouseRightButtonUp="btn02_RightClick" DataContext="{Binding IsAlive}"/>
<Button x:Name="btn03" Content="" Grid.Column="0" Grid.Row="3" Height="Auto" Width="Auto" Click="btn03_Click" MouseRightButtonUp="btn03_RightClick" DataContext="{Binding IsAlive}"/>
<Button x:Name="btn04" Content="" Grid.Column="0" Grid.Row="4" Height="Auto" Width="Auto" Click="btn04_Click" MouseRightButtonUp="btn04_RightClick" DataContext="{Binding IsAlive}"/>
<Button x:Name="btn05" Content="" Grid.Column="0" Grid.Row="5" Height="Auto" Width="Auto" Click="btn05_Click" MouseRightButtonUp="btn05_RightClick" DataContext="{Binding IsAlive}"/>
<Button x:Name="btn06" Content="" Grid.Column="0" Grid.Row="6" Height="Auto" Width="Auto" Click="btn06_Click" MouseRightButtonUp="btn06_RightClick" DataContext="{Binding IsAlive}"/>
<Button x:Name="btn07" Content="" Grid.Column="0" Grid.Row="7" Height="Auto" Width="Auto" Click="btn07_Click" MouseRightButtonUp="btn07_RightClick" DataContext="{Binding IsAlive}"/>
<Button x:Name="btn08" Content="" Grid.Column="0" Grid.Row="8" Height="Auto" Width="Auto" Click="btn08_Click" MouseRightButtonUp="btn08_RightClick" DataContext="{Binding IsAlive}"/>
<Button x:Name="btn09" Content="" Grid.Column="0" Grid.Row="9" Height="Auto" Width="Auto" Click="btn09_Click" MouseRightButtonUp="btn09_RightClick" DataContext="{Binding IsAlive}"/>
<Button x:Name="btn10" Content="" Grid.Column="1" Grid.Row="0" Height="Auto" Width="Auto"/>
<Button x:Name="btn11" Content="" Grid.Column="1" Grid.Row="1" Height="Auto" Width="Auto"/>
<Button x:Name="btn12" Content="" Grid.Column="1" Grid.Row="2" Height="Auto" Width="Auto"/>
<Button x:Name="btn13" Content="" Grid.Column="1" Grid.Row="3" Height="Auto" Width="Auto"/>
<Button x:Name="btn14" Content="" Grid.Column="1" Grid.Row="4" Height="Auto" Width="Auto"/>
<Button x:Name="btn15" Content="" Grid.Column="1" Grid.Row="5" Height="Auto" Width="Auto"/>
<Button x:Name="btn16" Content="" Grid.Column="1" Grid.Row="6" Height="Auto" Width="Auto"/>
<Button x:Name="btn17" Content="" Grid.Column="1" Grid.Row="7" Height="Auto" Width="Auto"/>
<Button x:Name="btn18" Content="" Grid.Column="1" Grid.Row="8" Height="Auto" Width="Auto"/>
<Button x:Name="btn19" Content="" Grid.Column="1" Grid.Row="9" Height="Auto" Width="Auto"/>
<Button x:Name="btn20" Content="" Grid.Column="2" Grid.Row="0" Height="Auto" Width="Auto"/>
<Button x:Name="btn21" Content="" Grid.Column="2" Grid.Row="1" Height="Auto" Width="Auto"/>
<Button x:Name="btn22" Content="" Grid.Column="2" Grid.Row="2" Height="Auto" Width="Auto"/>
<Button x:Name="btn23" Content="" Grid.Column="2" Grid.Row="3" Height="Auto" Width="Auto"/>
<Button x:Name="btn24" Content="" Grid.Column="2" Grid.Row="4" Height="Auto" Width="Auto"/>
<Button x:Name="btn25" Content="" Grid.Column="2" Grid.Row="5" Height="Auto" Width="Auto"/>
<Button x:Name="btn26" Content="" Grid.Column="2" Grid.Row="6" Height="Auto" Width="Auto"/>
<Button x:Name="btn27" Content="" Grid.Column="2" Grid.Row="7" Height="Auto" Width="Auto"/>
<Button x:Name="btn28" Content="" Grid.Column="2" Grid.Row="8" Height="Auto" Width="Auto"/>
<Button x:Name="btn29" Content="" Grid.Column="2" Grid.Row="9" Height="Auto" Width="Auto"/>
<Button x:Name="btn30" Content="" Grid.Column="3" Grid.Row="0" Height="Auto" Width="Auto"/>
<Button x:Name="btn31" Content="" Grid.Column="3" Grid.Row="1" Height="Auto" Width="Auto"/>
<Button x:Name="btn32" Content="" Grid.Column="3" Grid.Row="2" Height="Auto" Width="Auto"/>
<Button x:Name="btn33" Content="" Grid.Column="3" Grid.Row="3" Height="Auto" Width="Auto"/>
<Button x:Name="btn34" Content="" Grid.Column="3" Grid.Row="4" Height="Auto" Width="Auto"/>
<Button x:Name="btn35" Content="" Grid.Column="3" Grid.Row="5" Height="Auto" Width="Auto"/>
<Button x:Name="btn36" Content="" Grid.Column="3" Grid.Row="6" Height="Auto" Width="Auto"/>
<Button x:Name="btn37" Content="" Grid.Column="3" Grid.Row="7" Height="Auto" Width="Auto"/>
<Button x:Name="btn38" Content="" Grid.Column="3" Grid.Row="8" Height="Auto" Width="Auto"/>
<Button x:Name="btn39" Content="" Grid.Column="3" Grid.Row="9" Height="Auto" Width="Auto"/>
<Button x:Name="btn40" Content="" Grid.Column="4" Grid.Row="0" Height="Auto" Width="Auto"/>
<Button x:Name="btn41" Content="" Grid.Column="4" Grid.Row="1" Height="Auto" Width="Auto"/>
<Button x:Name="btn42" Content="" Grid.Column="4" Grid.Row="2" Height="Auto" Width="Auto"/>
<Button x:Name="btn43" Content="" Grid.Column="4" Grid.Row="3" Height="Auto" Width="Auto"/>
<Button x:Name="btn44" Content="" Grid.Column="4" Grid.Row="4" Height="Auto" Width="Auto"/>
<Button x:Name="btn45" Content="" Grid.Column="4" Grid.Row="5" Height="Auto" Width="Auto"/>
<Button x:Name="btn46" Content="" Grid.Column="4" Grid.Row="6" Height="Auto" Width="Auto"/>
<Button x:Name="btn47" Content="" Grid.Column="4" Grid.Row="7" Height="Auto" Width="Auto"/>
<Button x:Name="btn48" Content="" Grid.Column="4" Grid.Row="8" Height="Auto" Width="Auto"/>
<Button x:Name="btn49" Content="" Grid.Column="4" Grid.Row="9" Height="Auto" Width="Auto"/>
<Button x:Name="btn50" Content="" Grid.Column="5" Grid.Row="0" Height="Auto" Width="Auto"/>
<Button x:Name="btn51" Content="" Grid.Column="5" Grid.Row="1" Height="Auto" Width="Auto"/>
<Button x:Name="btn52" Content="" Grid.Column="5" Grid.Row="2" Height="Auto" Width="Auto"/>
<Button x:Name="btn53" Content="" Grid.Column="5" Grid.Row="3" Height="Auto" Width="Auto"/>
<Button x:Name="btn54" Content="" Grid.Column="5" Grid.Row="4" Height="Auto" Width="Auto"/>
<Button x:Name="btn55" Content="" Grid.Column="5" Grid.Row="5" Height="Auto" Width="Auto"/>
<Button x:Name="btn56" Content="" Grid.Column="5" Grid.Row="6" Height="Auto" Width="Auto"/>
<Button x:Name="btn57" Content="" Grid.Column="5" Grid.Row="7" Height="Auto" Width="Auto"/>
<Button x:Name="btn58" Content="" Grid.Column="5" Grid.Row="8" Height="Auto" Width="Auto"/>
<Button x:Name="btn59" Content="" Grid.Column="5" Grid.Row="9" Height="Auto" Width="Auto"/>
<Button x:Name="btn60" Content="" Grid.Column="6" Grid.Row="0" Height="Auto" Width="Auto"/>
<Button x:Name="btn61" Content="" Grid.Column="6" Grid.Row="1" Height="Auto" Width="Auto"/>
<Button x:Name="btn62" Content="" Grid.Column="6" Grid.Row="2" Height="Auto" Width="Auto"/>
<Button x:Name="btn63" Content="" Grid.Column="6" Grid.Row="3" Height="Auto" Width="Auto"/>
<Button x:Name="btn64" Content="" Grid.Column="6" Grid.Row="4" Height="Auto" Width="Auto"/>
<Button x:Name="btn65" Content="" Grid.Column="6" Grid.Row="5" Height="Auto" Width="Auto"/>
<Button x:Name="btn66" Content="" Grid.Column="6" Grid.Row="6" Height="Auto" Width="Auto"/>
<Button x:Name="btn67" Content="" Grid.Column="6" Grid.Row="7" Height="Auto" Width="Auto"/>
<Button x:Name="btn68" Content="" Grid.Column="6" Grid.Row="8" Height="Auto" Width="Auto"/>
<Button x:Name="btn69" Content="" Grid.Column="6" Grid.Row="9" Height="Auto" Width="Auto"/>
<Button x:Name="btn70" Content="" Grid.Column="7" Grid.Row="0" Height="Auto" Width="Auto"/>
<Button x:Name="btn71" Content="" Grid.Column="7" Grid.Row="1" Height="Auto" Width="Auto"/>
<Button x:Name="btn72" Content="" Grid.Column="7" Grid.Row="2" Height="Auto" Width="Auto"/>
<Button x:Name="btn73" Content="" Grid.Column="7" Grid.Row="3" Height="Auto" Width="Auto"/>
<Button x:Name="btn74" Content="" Grid.Column="7" Grid.Row="4" Height="Auto" Width="Auto"/>
<Button x:Name="btn75" Content="" Grid.Column="7" Grid.Row="5" Height="Auto" Width="Auto"/>
<Button x:Name="btn76" Content="" Grid.Column="7" Grid.Row="6" Height="Auto" Width="Auto"/>
<Button x:Name="btn77" Content="" Grid.Column="7" Grid.Row="7" Height="Auto" Width="Auto"/>
<Button x:Name="btn78" Content="" Grid.Column="7" Grid.Row="8" Height="Auto" Width="Auto"/>
<Button x:Name="btn79" Content="" Grid.Column="7" Grid.Row="9" Height="Auto" Width="Auto"/>
<Button x:Name="btn80" Content="" Grid.Column="8" Grid.Row="0" Height="Auto" Width="Auto"/>
<Button x:Name="btn81" Content="" Grid.Column="8" Grid.Row="1" Height="Auto" Width="Auto"/>
<Button x:Name="btn82" Content="" Grid.Column="8" Grid.Row="2" Height="Auto" Width="Auto"/>
<Button x:Name="btn83" Content="" Grid.Column="8" Grid.Row="3" Height="Auto" Width="Auto"/>
<Button x:Name="btn84" Content="" Grid.Column="8" Grid.Row="4" Height="Auto" Width="Auto"/>
<Button x:Name="btn85" Content="" Grid.Column="8" Grid.Row="5" Height="Auto" Width="Auto"/>
<Button x:Name="btn86" Content="" Grid.Column="8" Grid.Row="6" Height="Auto" Width="Auto"/>
<Button x:Name="btn87" Content="" Grid.Column="8" Grid.Row="7" Height="Auto" Width="Auto"/>
<Button x:Name="btn88" Content="" Grid.Column="8" Grid.Row="8" Height="Auto" Width="Auto"/>
<Button x:Name="btn89" Content="" Grid.Column="8" Grid.Row="9" Height="Auto" Width="Auto"/>
<Button x:Name="btn90" Content="" Grid.Column="9" Grid.Row="0" Height="Auto" Width="Auto"/>
<Button x:Name="btn91" Content="" Grid.Column="9" Grid.Row="1" Height="Auto" Width="Auto"/>
<Button x:Name="btn92" Content="" Grid.Column="9" Grid.Row="2" Height="Auto" Width="Auto"/>
<Button x:Name="btn93" Content="" Grid.Column="9" Grid.Row="3" Height="Auto" Width="Auto"/>
<Button x:Name="btn94" Content="" Grid.Column="9" Grid.Row="4" Height="Auto" Width="Auto"/>
<Button x:Name="btn95" Content="" Grid.Column="9" Grid.Row="5" Height="Auto" Width="Auto"/>
<Button x:Name="btn96" Content="" Grid.Column="9" Grid.Row="6" Height="Auto" Width="Auto"/>
<Button x:Name="btn97" Content="" Grid.Column="9" Grid.Row="7" Height="Auto" Width="Auto"/>
<Button x:Name="btn98" Content="" Grid.Column="9" Grid.Row="8" Height="Auto" Width="Auto"/>
<Button x:Name="btn99" Content="" Grid.Column="9" Grid.Row="9" Height="Auto" Width="Auto"/>
</Grid>
</Grid>
You can create entire grid with just few lines of XAML code. ;-)
Using magic of MVVM
Create ViewModel class for managing buttons. Let it have an ObservableCollection of your buttons' data. I've also created a variable which sets number of columns of our grid.
public ObservableCollection<GridButton> GridButtonList { get; set; } = new ObservableCollection<GridButton>();
public int GridColumns { get; set; }
Then, create basic class for storing data of each button — like background and defined actions for left and right mouse click. It's important to use Properties instead of regular variables, as it'll allow you to use them directly in XAML bindings. You may need to extend those to make use of PropertyChanged event, which I'll explain later.
class GridButton
{
public string Text { get; set; }
public Brush Background { get; set; }
public ICommand OnLeftClick { get; set; }
public ICommand OnRightClick { get; set; }
}
Next, we can create a View based on UserControl for displaying just those buttons.
<UserControl ...>
<UserControl.DataContext>
<!-- Binding previously created ViewModel to our View -->
<ViewModel:ButtonGridViewModel />
</UserControl.DataContext>
<ItemsControl ItemsSource="{Binding GridButtonList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="{Binding GridColumns}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Text}" Background="{Binding Background}" Command="{Binding OnClick}" CommandParameter="{Binding}">
<Button.InputBindings>
<MouseBinding Gesture="RightClick" Command="{Binding OnRightClick}" CommandParameter="{Binding}" />
</Button.InputBindings>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
Notice that we'll import all the buttons from the variable GridButtonList defined in our ViewModel. It doesn't matter how much buttons you'll have, XAML will not change from now on.
I recommend using UniformGrid which will automatically arrange items on the plane. You can optionally define both Rows and Columns as a hint for the grid. The upside is that every item will have the same width and height which seems to be perfect for your application.
We're providing collections of objects GridButton, which means that every item in ItemsControl will be of that type. We're instructing it to use data from GridButton class to render Button for each item. For standard left click we'll use default Command property with appropriate action defined in GridButton.OnLeftClick. As for right click, we'll use InputBindings where we can define detailed gesture to fire the next action — GridButton.OnRightClick. Full list of available Mouse Gestures is in documentation. Similar to MouseBinding is KeyBinding which supports firing commands based on keyboard gestures.
Populating the buttons' collection
The following code will create 81 buttons with individual actions. Thanks to XAML binding each button will have a text inside corresponding to its location in format XxY. Notice that we can use only one loop to create a grid, thanks to Modulo operator.
GridColumns = 9;
var itemCount = Math.Pow(GridColumns, 2);
for (var i = 0; i < itemCount; ++i)
{
var btn = new GridButton()
{
Text = string.Format("{0}x{1}", i % GridColumns + 1, i / GridColumns + 1),
OnClick = new RelayCommand<GridButton>((b) =>
{
b.Background = Brushes.Green;
}),
OnRightClick = new RelayCommand<GridButton>((b) =>
{
b.Background = Brushes.Red;
})
};
GridButtonList.Add(btn);
}
Helper classes
I used 2 classes that help make everything work, RelayCommand for Command support and ObservableObject which helps bring our data bindings to life. Both of which I listed below:
internal class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChangedEvent(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class RelayCommand<T> : ICommand
{
#region Fields
readonly Action<T> _execute = null;
readonly Predicate<T> _canExecute = null;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of <see cref="DelegateCommand{T}"/>.
/// </summary>
/// <param name="execute">Delegate to execute when Execute is called on the command. This can be null to just hook up a CanExecute delegate.</param>
/// <remarks><seealso cref="CanExecute"/> will always return true.</remarks>
public RelayCommand(Action<T> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<T> execute, Predicate<T> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
///<summary>
///Defines the method that determines whether the command can execute in its current state.
///</summary>
///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
///<returns>
///true if this command can be executed; otherwise, false.
///</returns>
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute((T)parameter);
}
///<summary>
///Occurs when changes occur that affect whether or not the command should execute.
///</summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
///<summary>
///Defines the method to be called when the command is invoked.
///</summary>
///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null" />.</param>
public void Execute(object parameter)
{
_execute((T)parameter);
}
#endregion
}
Working example
I took a liberty of creating sample project for you to analyse. You can check it out on GitHub: https://github.com/xerif-examples/WPF-ButtonGridTest
I recommend using MVVM to write less code.
Hope that helps,
~Wiktor
You can use the GetValue() function of a UIElement, in this case, a Button, then casting the object returned to the appropriate type, in this case, an int.
int row = (int)button.GetValue(Grid.RowProperty);
int col = (int)button.GetValue(Grid.ColumnProperty);
You can then use these values in your for loop to do whatever it is you need to do.