Binding IsVisible to a bool property in Xamarin Forms - xamarin.forms

I've got a label that I want to bind to a boolean property (HasNotifications). However, when the property is false, the label stays visible. If I set the IsVisible property to false in the XAML, the label isn't visible so the issue appears to be with the binding.
XAML:
<AbsoluteLayout
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0,0,1,1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Text="Title"
HorizontalOptions="Center"
VerticalOptions="Center"
TextColor="White"
FontSize="Large"
FontAttributes="Bold"
Margin="5"
BindingContext="{x:Reference DashboardPageView}"
Grid.Row="0" />
<Label
Text="Notifications"
HorizontalOptions="Start"
VerticalOptions="Center"
TextColor="White"
FontSize="Medium"
FontAttributes="Bold"
Margin="3"
BindingContext="{x:Reference DashboardPageView}"
IsVisible="{Binding HasNotifications}"
Grid.Row="1" />
</Grid>
</AbsoluteLayout>
My viewmodel:
public bool HasNotifications
{
get => this.hasNotifications;
set => this.SetProperty(ref this.hasNotifications, value);
}

I don't think you have set the correct BindingContext. The HasNotifications is a property of your ViewModel while the BindingContext you set to your label is DashboardPageView.
I wrote a simple demo and hope you can get some idea from it:
In xaml:
<Grid
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0,0,1,1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Text="Title"
HorizontalOptions="Center"
VerticalOptions="Center"
TextColor="Black"
FontSize="Large"
FontAttributes="Bold"
Margin="5"
Grid.Row="0" />
<Label
Text="Notifications"
HorizontalOptions="Start"
VerticalOptions="Center"
TextColor="Black"
FontSize="Medium"
FontAttributes="Bold"
Margin="3"
IsVisible="{Binding HasNotifications}"
Grid.Row="1" />
<Button Text="change HasNotifications" Clicked="Button_Clicked" Grid.Row="2"/>
</Grid>
In cs:
public partial class MainPage : ContentPage
{
ViewModel myViewModel;
public MainPage()
{
InitializeComponent();
myViewModel = new ViewModel();
BindingContext = myViewModel;
}
private void Button_Clicked(object sender, EventArgs e)
{
myViewModel.HasNotifications = !myViewModel.HasNotifications;
}
}
public class ViewModel : INotifyPropertyChanged
{
bool _HasNotifications;
public event PropertyChangedEventHandler PropertyChanged;
public ViewModel()
{
}
public bool HasNotifications
{
set
{
if (_HasNotifications != value)
{
_HasNotifications = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("HasNotifications"));
}
}
}
get
{
return _HasNotifications;
}
}
}
Feel free to ask me any question if you have.

Related

Load ContentView inside CarouselView in Xamarn forms

I am trying to create a scrollable tabs in Xamarin.Forms with CollectionView and CarouselView as specified in this link. I need to load different ContentView in CarouselView based on the Tab selected in the header.
I tried like below but the ContentView is not displaying..
Below is xaml Code:
<Grid x:DataType="{x:Null}" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="45" />
<RowDefinition Height="45" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<CollectionView
x:Name="CustomTabsView"
Grid.Row="1"
HorizontalScrollBarVisibility="Never"
ItemSizingStrategy="MeasureAllItems"
ItemsSource="{Binding TabVms}"
ItemsUpdatingScrollMode="KeepItemsInView"
SelectedItem="{Binding CurrentTabVm, Mode=TwoWay}"
SelectionMode="Single"
VerticalScrollBarVisibility="Never">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:TabViewModel">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="3" />
</Grid.RowDefinitions>
<Label
x:Name="TitleLabel"
Grid.Row="0"
Padding="15,0"
FontAttributes="Bold"
FontSize="Small"
HeightRequest="50"
HorizontalTextAlignment="Center"
Text="{Binding Title}"
TextColor="White"
VerticalTextAlignment="Center" />
<BoxView
x:Name="ActiveIndicator"
Grid.Row="1"
BackgroundColor="Red"
IsVisible="{Binding IsSelected, Mode=TwoWay}" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<CarouselView
Grid.Row="2"
CurrentItem="{Binding CurrentTabVm, Mode=TwoWay}"
CurrentItemChanged="CarouselView_CurrentItemChanged"
HorizontalScrollBarVisibility="Never"
IsScrollAnimated="True"
IsSwipeEnabled="True"
ItemsSource="{Binding TabVms}"
VerticalScrollBarVisibility="Never">
<CarouselView.ItemTemplate>
<DataTemplate x:DataType="local:TabViewModel">
<ContentView
x:Name="dynamiccontent"
BackgroundColor="White"
Content="{Binding DynamicContentView, Mode=TwoWay}" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</Grid>
.cs file Code
private void CarouselView_CurrentItemChanged(object sender, CurrentItemChangedEventArgs e)
{
var x = e.CurrentItem as TabItem;
var viewModel = BindingContext as xxxViewModel;
if(x.Header == Tab1)
{
viewModel.TabVms[0].DynamicContentView = new Page1();
}
if(x.Header == Tab2)
{
viewModel.TabVms[1].DynamicContentView = new Page2();
}
}
Any help is appreciated!
You could use DataTemplateSelector.
Creating a DataTemplateSelector:
class DymaicDataTemplateSelector : DataTemplateSelector
{
public DataTemplate Tab1Template { get; set; }
public DataTemplate Tab2Template { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return ((TabViewModel)item).Header == "Tab1" ? Tab1Template : Tab2Template;
}
}
Consuming a DataTemplateSelector in XAML:
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="tab1Template" x:DataType="local:TabViewModel">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Margin="10"
LineBreakMode="WordWrap"
Text="{Binding Content}"
TextColor="Red"
VerticalTextAlignment="Center" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="tab2Template" x:DataType="local:TabViewModel">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Margin="10"
LineBreakMode="WordWrap"
Text="{Binding Content}"
TextColor="Green"
VerticalTextAlignment="Center" />
</Grid>
</DataTemplate>
<local:DymaicDataTemplateSelector
x:Key="dymaicDataTemplateSelector"
Tab1Template="{StaticResource tab1Template}"
Tab2Template="{StaticResource tab2Template}" />
</ResourceDictionary>
</ContentPage.Resources>
Assign it to the ItemTemplate property:
<CarouselView
Grid.Row="2"
CurrentItem="{Binding CurrentTabVm, Mode=TwoWay}"
CurrentItemChanged="CarouselView_CurrentItemChanged"
HorizontalScrollBarVisibility="Never"
IsScrollAnimated="True"
IsSwipeEnabled="True"
ItemTemplate="{StaticResource dymaicDataTemplateSelector}"
ItemsSource="{Binding TabVms}"
VerticalScrollBarVisibility="Never" />

On using Detect Shake functionality in xamarin.forms UI is calling multiple times

I am working with xamarin.forms shake delect functionality, where on shaking the mobile I am calling a popup screen, but that screen is calling multiple times till I wont stop shaking the phone
RateUsPage.xaml
<?xml version="1.0" encoding="UTF-8"?>
<pages:PopupPage Title="Rate Us"
BackgroundColor="{DynamicResource TransparentPurple}"
Padding="0">
<pages:PopupPage.Animation>
<animations:ScaleAnimation PositionIn="Center" PositionOut="Center" ScaleIn="1.2" ScaleOut="0.8" DurationIn="400" DurationOut="300" EasingIn="SinOut" EasingOut="SinIn" HasBackgroundAnimation="True" />
</pages:PopupPage.Animation>
<StackLayout VerticalOptions="Center" HorizontalOptions="Center" Margin="20">
<StackLayout>
<Label Text="Rate Your Experience !!!" FontSize="{DynamicResource FontSize14}"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding Star1}" Grid.Row="0" Grid.Column="0">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding StarTappedCommand}" CommandParameter="1"/>
</Image.GestureRecognizers>
</Image>
<Image Source="{Binding Star2}" Grid.Row="0" Grid.Column="1">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding StarTappedCommand}" CommandParameter="2"/>
</Image.GestureRecognizers>
</Image>
<Image Source="{Binding Star3}" Grid.Row="0" Grid.Column="2">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding StarTappedCommand}" CommandParameter="3"/>
</Image.GestureRecognizers>
</Image>
<Image Source="{Binding Star4}" Grid.Row="0" Grid.Column="3">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding StarTappedCommand}" CommandParameter="4"/>
</Image.GestureRecognizers>
</Image>
<Image Source="{Binding Star5}" Grid.Row="0" Grid.Column="4">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding StarTappedCommand}" CommandParameter="5"/>
</Image.GestureRecognizers>
</Image>
</Grid>
</StackLayout>
<StackLayout>
<Grid Padding="10" RowSpacing="0" ColumnSpacing="15" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Button Padding="0" Grid.Row="0" Grid.Column="0" Command="{Binding CloseCommand}" FontSize="{DynamicResource FontSize14}" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Text="{Binding CancelText}"/>
</Grid>
</StackLayout>
</StackLayout>
</pages:PopupPage>
RateUsPageViewModel.cs
public class RateUsPageViewModel{
public RateUsPageViewModel(){
try
{
if (Accelerometer.IsMonitoring)
Accelerometer.Stop();
else
Accelerometer.Start(SensorSpeed.Game);
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Other error has occurred.
}
Accelerometer.ShakeDetected += Accelerometer_ShakeDetected;
}
private void Accelerometer_ShakeDetected(object sender, EventArgs e)
{
MainThread.BeginInvokeOnMainThread(() =>
{
_navigationService.ShowPopup<RatingUsPageViewModel>();
});
}
}
so when I use this code my UI is calling number of times
please help
thanks in advance
Remove your try and catch blocks and implement ToggleAccelerometer() method. call ToggleAccelerometer() method in your constructor and then again call in Accelerometer_ShakeDetected(object sender, EventArgs e). It should stop your problem.
public class RateUsPageViewModel
{
public RateUsPageViewModel()
{
ToggleAccelerometer();
Accelerometer.ShakeDetected += Accelerometer_ShakeDetected;
}
private void Accelerometer_ShakeDetected(object sender, EventArgs e)
{
MainThread.BeginInvokeOnMainThread(() =>
{
ToggleAccelerometer();
_navigationService.ShowPopup<RatingUsPageViewModel>();
});
}
public void ToggleAccelerometer()
{
try
{
if (Accelerometer.IsMonitoring)
Accelerometer.Stop();
else
Accelerometer.Start(speed);
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Other error has occurred.
}
}
}

Can you define RowDefinition in style xamarin forms

I have the following
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="1.5*"></RowDefinition>
<RowDefinition Height="7.5*"></RowDefinition>
</Grid.RowDefinitions>
and I would like to define the Height in a Style or in a variable in the app.xaml.
<Grid.RowDefinitions>
<RowDefinition Height="{StaticResource myHeight}"></RowDefinition>
<RowDefinition Height="{StaticResource myHeight2}"></RowDefinition>
</Grid.RowDefinitions>
Is this possible? I have tried but I get an error.
The reason I want to achieve this is that on small devices I need to change the row height.
I would appreciate any tips or suggestions.
You can bind a model to ContentPage , then Grid can use binded data by model and row height can be setted by model data (contain row height paramaters).
For example , create a sample ViewModel(RowHeightClass) as follow :
using Xamarin.Essentials;
public class RowHeightClass
{
public GridLength rowFirstHeight { set; get; }
public GridLength rowSecondHeight { set; get; }
public RowHeightClass()
{
// here can add code set by device screen
var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
double screenheight = mainDisplayInfo.Height;
rowFirstHeight = new GridLength(DeviceDisplay * 0.2);
rowSecondHeight = new GridLength(DeviceDisplay * 0.4);
}
}
Binding it in ContentPage :
RowHeightClass rowHeightClass = new RowHeightClass();
BindingContext = rowHeightClass;
Used in XAML :
<Grid VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="{Binding rowFirstHeight}" />
<RowDefinition Height="{Binding rowSecondHeight}" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<BoxView Grid.Row="0"
Grid.Column="0"
BackgroundColor="Blue" />
<BoxView Grid.Row="1"
Grid.Column="0"
BackgroundColor="Red" />
<Button Grid.Row="2"
Grid.Column="0"
BackgroundColor="Yellow"
Clicked="Button_Clicked" />
</Grid>
Note : You can modify the constructor method of RowHeightClass to add method to set needed height by the size of device screen .
==================================Update=====================================
Using StaticResource also can set the heigh of row . Add a Resources for Grid or Application as follow :
<Grid VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<Grid.Resources>
<ResourceDictionary>
<x:Double x:Key="SmallScreenRowheight">200</x:Double>
<x:Double x:Key="LargeScreenRowheight">400</x:Double>
</ResourceDictionary>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="{StaticResource SmallScreenRowheight}" />
<RowDefinition Height="{StaticResource LargeScreenRowheight}" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<BoxView Grid.Row="0"
Grid.Column="0"
BackgroundColor="Blue" />
<BoxView Grid.Row="1"
Grid.Column="0"
BackgroundColor="Red" />
<Button Grid.Row="2"
Grid.Column="0"
BackgroundColor="Yellow"
Clicked="Button_Clicked" />
</Grid>

How to get the itemlistview details when a button is clicked

When a Add to cart button is clicked i want clicked row to add to local database.
i tried to implement clicked option, but is shows System.InvalidCastException: Specified cast is not valid.
My Xaml is :
<controls:FlowListView x:Name="gallery"
FlowColumnCount="2"
SeparatorVisibility="Default"
HasUnevenRows="True"
FlowItemsSource="{Binding ItemsGallery}"
FlowUseAbsoluteLayoutInternally="True"
FlowItemTapped="OnFlowItemTapped"
FlowColumnExpand="Proportional"
BackgroundColor="White">
<controls:FlowListView.FlowColumnTemplate>
<DataTemplate>
<StackLayout>
<Frame BorderColor="#DCDCDC" HasShadow="True" Margin="2,2,2,2" CornerRadius="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="35"/>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
<ffimageloading:CachedImage Source="{Binding image}" Grid.Row="0" LoadingPlaceholder="ItemsGallery" HeightRequest="120" WidthRequest="120" />
<Label Grid.Row="1"
VerticalOptions="End"
FontAttributes="Bold"
FontSize="Medium"
HorizontalTextAlignment="Start"
TextColor="Black"
Text="{Binding name}" />
<Label Grid.Row="2" HorizontalOptions="Start"
VerticalOptions="End"
FontAttributes="Bold"
FontSize="Medium"
Text="{Binding weight}" />
<Label HorizontalOptions="Start" Grid.Row="3"
VerticalOptions="End"
FontAttributes="Bold"
FontSize="Medium"
Margin="2"
Text="{Binding price}" />
<Button Text="Add TO Cart" Grid.Row="4" BackgroundColor="Coral" TextColor="WhiteSmoke" Clicked="Button_Clicked_1" />
</Grid>
</Frame>
</StackLayout>
</DataTemplate>
</controls:FlowListView.FlowColumnTemplate>
</controls:FlowListView>
and my logic is :
private async void Button_Clicked_1(object sender, EventArgs e)
{
if (((ListView)sender).SelectedItem == null)
return;
var myList = (ListView)sender;
var myProuct= (myList.SelectedItem as ProductDetail);
}
the sender of a Button Click event will be a BUTTON, not the ListView containing the button
private async void Button_Clicked_1(object sender, EventArgs e) {
// the sender of a button click event is a BUTTON
var btn = (Button)sender;
var myProduct = (ProductDetail)btn.BindingContext;
}
You could go with regular data binding way with viewmodel, or you can try this
Button Text="Add TO Cart" Grid.Row="4" BackgroundColor="Coral" TextColor="WhiteSmoke" Command="{Binding AddCommand}" CommandParameter = "{Binding .}"
But then you would need to edit the model building up ItemsGallery list.
public ICommand AddCommand { get; set; }
And when you are creating your objects
new Gallery
{
//your stuff
AddCommand = new Command<Gallery>(async (item) => await
AddItem(item))
})
private async Task AddItem(Gallery item)
{
//your implementation
}

how rebind silverlight datagrid

I am just doing simple example in Silverlight, which retrieves data from database, can also insert, update and delete
I use child window for insert command, when I click "OK" Button at this ChildWindow it insert's in database but not renders on page(Silverlight content), there is same records therefore in database really inserts information. only after again re-lunch this page, it shows correctly(retrieves all data from server)
I'll post my source
this is Customers.xaml file
<UserControl x:Class="Store.Customers"
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:mv="clr-namespace:Store.ViewModel"
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="1000">
<UserControl.Resources>
<mv:ViewModel x:Key="ViewModel"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="127*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="130*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="91*" />
<RowDefinition Height="99*" />
<RowDefinition Height="110*" />
</Grid.RowDefinitions>
<Button Name="btnEdit" Content="Edit" HorizontalAlignment="Right" Grid.Column="1" Width="55" Height="30" Margin="0,225,0,0" Click="btnEdit_Click" />
<data:DataGrid Name="dgCustomer"
AutoGenerateColumns="False" VerticalScrollBarVisibility="Visible"
ItemsSource="{Binding PagedView, Mode=TwoWay, Source={StaticResource ViewModel}}"
Grid.Row="1" Grid.Column="1">
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="ID" Binding="{Binding CustomerID}"/>
<data:DataGridTextColumn Header="CompanyName" Binding="{Binding CompanyName}"/>
<data:DataGridTextColumn Header="ContactName" Binding="{Binding ContactName}"/>
<data:DataGridTextColumn Header="ContactTitle" Binding="{Binding ContactTitle}"/>
<data:DataGridTextColumn Header="Address" Binding="{Binding Address}"/>
<data:DataGridTextColumn Header="City" Binding="{Binding City}"/>
<data:DataGridTextColumn Header="Region" Binding="{Binding Region}"/>
<data:DataGridTextColumn Header="PostalCode" Binding="{Binding PostalCode}"/>
<data:DataGridTextColumn Header="Country" Binding="{Binding Country}"/>
<data:DataGridTextColumn Header="Phone" Binding="{Binding Phone}"/>
<data:DataGridTextColumn Header="Fax" Binding="{Binding Fax}"/>
<data:DataGridCheckBoxColumn Header="IsCitizen" Binding="{Binding IsCitizen}"/>
</data:DataGrid.Columns>
</data:DataGrid>
<data:DataPager HorizontalContentAlignment="Center" x:Name="myPager"
Source="{Binding ItemsSource, ElementName=dgCustomer}"
AutoEllipsis="True"
PageSize="10" Grid.Row="2" Grid.Column="1" VerticalAlignment="Top"/>
</Grid>
and this codebehinde
public partial class Customers : UserControl
{
public Customers()
{
InitializeComponent();
}
private void btnEdit_Click(object sender, RoutedEventArgs e)
{
new AddNewCustomer().Show();
}
}
this is childwindow
<controls:ChildWindow x:Class="Store.AddNewCustomer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:mv="clr-namespace:Store.ViewModel"
Width="450" Height="350"
Title="AddNewCustomer" >
<controls:ChildWindow.Resources>
<mv:ViewModel x:Key="ViewModel"/>
</controls:ChildWindow.Resources>
<Grid x:Name="LayoutRoot" Margin="2">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid>
<Grid.RowDefinitions >
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="30*"></ColumnDefinition>
<ColumnDefinition Width="70*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Customer ID :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtCustomerID"
Text="{Binding CustomerID, Mode=TwoWay, Source={StaticResource ViewModel}}" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="Company Name :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtCompanyName"
Text="{Binding CompanyName, Mode=TwoWay, Source={StaticResource ViewModel}}"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Contact Name :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="3" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtContactName" />
<TextBlock Grid.Row="4" Grid.Column="0" Text="Contact Title :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="4" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtContactTitle" />
<TextBlock Grid.Row="5" Grid.Column="0" Text="Address :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="5" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtAddressTitle" />
<TextBlock Grid.Row="6" Grid.Column="0" Text="City :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="6" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtCity" />
<TextBlock Grid.Row="7" Grid.Column="0" Text="Country :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="7" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtCountry" />
</Grid>
<Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1" />
<Button x:Name="OKButton" Content="OK" Width="75" Height="23" HorizontalAlignment="Right" Click="OKButton_Click"
Margin="0,12,79,0" Grid.Row="1" Command="{ Binding AddNewCustomer, Mode=TwoWay, Source={StaticResource ViewModel} }"/>
</Grid>
this is My ViewModel
public class ViewModel : BaseViewModel
{
#region Fields
public ObservableCollection<Customer> _items;
public PagedCollectionView _view;
public string _customerID;
public string _companyName;
#endregion
#region Constructors
public ViewModel()
{
if (!this.IsDesignTime)
this.LoadCustomer();
}
#endregion
#region Properties
public ICommand AddNewCustomer { get { return new AddNewCustomerInfo(this); } }
public ObservableCollection<Customer> Items
{
get { return this._items; }
set
{
this._items = value;
this.OnPropertyChanged("Items");
}
}
public PagedCollectionView PagedView
{
get { return this._view; }
set
{
this._view = value;
this.OnPropertyChanged("PagedView");
}
}
public string CustomerID
{
get { return this._customerID;}
set
{
this._customerID = value;
this.OnPropertyChanged("CustomerID");
}
}
public string CompanyName
{
get { return this._companyName; }
set
{
this._companyName = value;
this.OnPropertyChanged("CompanyName");
}
}
#endregion
#region Methods
public void LoadCustomer()
{
DataServiceClient webService = new DataServiceClient();
webService.GetCustomersCompleted += new EventHandler<GetCustomersCompletedEventArgs>(webService_GetCustomersCompleted);
webService.GetCustomersAsync();
}
public void webService_GetCustomersCompleted(object sender, GetCustomersCompletedEventArgs e)
{
Items = e.Result;
PagedCollectionView pageView = new PagedCollectionView(Items);
pageView.PageSize = 10;
PagedView = pageView;
}
public void CreateCustomer()
{
DataServiceClient webservice = new DataServiceClient();
Customer cust = new Customer();
cust.CustomerID = this.CustomerID;
cust.CompanyName = this.CompanyName;
webservice.InsertCustomerCompleted += new EventHandler<InsertCustomerCompletedEventArgs>(webservice_InsertCustomerCompleted);
webservice.InsertCustomerAsync(cust);
LoadCustomer();
}
void webservice_InsertCustomerCompleted(object sender, InsertCustomerCompletedEventArgs e)
{
this.CreateResult = e.Result;
}
#endregion
}
public class AddNewCustomerInfo : ICommand
{
#region Fields
public ViewModel ViewModel { get; set; }
#endregion
#region Constructors
public AddNewCustomerInfo(ViewModel viewModel)
{
this.ViewModel = viewModel;
}
#endregion
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
this.ViewModel.CreateCustomer();
}
}
Grid and childwindow looks like this
As a simple basic solution, i would do this:
change your InsertCustomer web service call to return the updated Customer object that it just saved. This is so you will get an updated copy of the data object, complete with any keys/IDs. Doing this is a reasonably efficient way to do it, as you are making a call and accessing the database anyway, there is no point making two calls when it can be done in one.
once you've changed your webservice contract and regenerated your client proxy, the InsertCustomerCompletedEventArgs Result property should contain the updated Customer object. If you now add this data object to your PagedCollectionView it will automatically show up in your grid (as the PagedCollectionView implements INotifyCollectionChanged so the DataGrid binding will pick it up straight away, although be aware that paging may mean it isn't visible in the list you are currently looking at).

Resources