How to prevent RadioButton unchecked once it is checked? - xaml

I've got an enum like this:
public enum DLTypeEnum
{
Others = 1, People = 2, Company = 4,
}
I have a property in my ViewModel like this:
private DLTypeEnum _DLType;
public DLTypeEnum DLType
{
get { return _DLType; }
set { SetProperty(ref _DLType, value); }
}
Here is my xaml:
<WrapPanel Grid.Row="3" Grid.Column="1">
<WrapPanel.Resources>
<Converter:EnumToBoolConverter x:Key="EnumToBooleanConverter" />
</WrapPanel.Resources>
<RadioButton GroupName="DLType" IsChecked="{Binding Path=DLType,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static dlAccount:DLTypeEnum.Others}}"/>
<RadioButton GroupName="DLType" IsChecked="{Binding Path=DLType,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static dlAccount:DLTypeEnum.People}}"/>
<RadioButton GroupName="DLType" IsChecked="{Binding Path=DLType,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static dlAccount:DLTypeEnum.Company}}"/>
</WrapPanel>
And this converter:
public class EnumToBoolConverter:IValueConverter
{
private int val;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int intParam = (int)parameter;
val = (int)value;
return ((intParam & val) != 0);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)//bool to enum
{
val ^= (int)parameter;
return Enum.Parse(targetType, val.ToString());
}
}
Once the RadioButton is checked, I don't want it to be unchecked unless it select the other RadioButton (ie. one RadioButton must be selected all the time).

Try this code:
<WrapPanel Grid.Row="3" Grid.Column="1">
<WrapPanel.Resources>
<Converter:EnumToBoolConverter x:Key="EnumToBooleanConverter" />
</WrapPanel.Resources>
<RadioButton GroupName="DLType" IsChecked="{Binding Path=DLType,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static dlAccount:DLTypeEnum.Others}}" Unchecked="RadioButton_Unchecked"/>
<RadioButton GroupName="DLType" IsChecked="{Binding Path=DLType,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static dlAccount:DLTypeEnum.People}}" Unchecked="RadioButton_Unchecked"/>
<RadioButton GroupName="DLType" IsChecked="{Binding Path=DLType,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static dlAccount:DLTypeEnum.Company}}" Unchecked="RadioButton_Unchecked"/>
</WrapPanel>
And Code behind:
private void RadioButton_Unchecked(object sender, RoutedEventArgs e)
{
if((_viewModel.DLss.CurrentItem as DL).DLType == 0)
((RadioButton)sender).IsChecked = true;
}

Related

Refresh SemanticZoom ObservableCollection in ViewModel

When using a SemanticZoom control, is there a way to update the ObservableCollection in the ViewModel after a table change? After making changes to the table in SQLite, within the same page (categories.xaml.cs), the SemanticZoom control does not update. Reloading the page from menu navigation does reload the page with the correct data. If the control just took an ObservableCollection as it's items source, the ObservableCollection could just be refreshed. Using a ViewModel was the only code example I could find for the SemanticZoom control. Thanks in advance!
categories.xaml
<Page.DataContext>
<vm:CategoriesViewModel></vm:CategoriesViewModel>
</Page.DataContext>
<Page.Resources>
<CollectionViewSource x:Name="Collection" IsSourceGrouped="true" ItemsPath="Items" Source="{Binding CategoryGroups}" />
</Page.Resources>
<SemanticZoom Name="szCategories" ScrollViewer.ZoomMode="Enabled">
<SemanticZoom.ZoomedOutView>
<GridView ScrollViewer.IsHorizontalScrollChainingEnabled="False">
<GridView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Group.Name }" Foreground="Gray" Margin="5" FontSize="25" />
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
<ListView Name="lvCategories" ItemsSource="{Binding Source={StaticResource Collection}}" Tapped="lvCategories_Tapped">
<ListView.ItemTemplate>
<DataTemplate x:DataType="data:Category">
<StackPanel>
<TextBlock Text="{Binding Title}" Margin="5" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text='{Binding Name}' Foreground="Gray" FontSize="25" Margin="5,5,5,0" />
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</SemanticZoom.ZoomedInView>
</SemanticZoom>
categories.xaml.cs
public Categories()
{
this.InitializeComponent();
var collectionGroups = Collection.View.CollectionGroups;
((ListViewBase)this.szCategories.ZoomedOutView).ItemsSource = collectionGroups;
}
CategoriesViewModel.cs
internal class CategoriesViewModel : BindableBase
{
public CategoriesViewModel()
{
CategoryGroups = new ObservableCollection<CategoryDataGroup>(CategoryDataGenerator.GetGroupedData());
}
private ObservableCollection<CategoryDataGroup> _groups;
public ObservableCollection<CategoryDataGroup> CategoryGroups
{
get { return _groups; }
set { SetProperty(ref _groups, value); }
}
}
public abstract class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (object.Equals(storage, value)) return false;
storage = value;
this.OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged(string propertyName)
{
var eventHandler = this.PropertyChanged;
if (eventHandler != null)
{
eventHandler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
SymanticZoom.cs
internal class CategoryDataGroup
{
public string Name { get; set; }
public List<CategoryData> Items { get; set; }
}
internal class CategoryData
{
public CategoryData(string grp, string title)
{
Grp = grp;
Title = title;
}
public string Grp { get; private set; }
public string Title { get; private set; }
}
internal class CategoryDataGenerator
{
private static List<CategoryData> _data;
public static List<CategoryDataGroup> GetGroupedData()
{
if (_data != null)
_data.Clear();
GenerateData();
return _data.GroupBy(d => d.Grp[0],
(key, items) => new CategoryDataGroup() { Name = key.ToString(), Items = items.ToList() }).ToList();
}
private static void GenerateData()
{
ObservableCollection<Category> ocCategories = new ObservableCollection<Category>();
SQLiteManager.Categories.Select(ocCategories);
_data = new List<CategoryData>();
foreach (var temp in ocCategories)
{
_data.Add(new CategoryData(temp.Name.Substring(0,1), temp.Name));
}
}
}
The zoomed-in view and zoomed-out view should be synchronized, so if a user selects a group in the zoomed-out view, the details of that same group are shown in the zoomed-in view. You can use a CollectionViewSource or add code to synchronize the views.
For more info, see Semantic zoom.
We can use CollectionViewSource control in our page, it provides a data source that adds grouping and current-item support to collection classes. Then we can bind the GridView.ItemSource and ListView.ItemSource to the CollectionViewSource. When we set new data to the CollectionViewSource, the GridView in SemanticZoom.ZoomedOutView and ListView in SemanticZoom.ZoomedInView will be updated.
xmlns:wuxdata="using:Windows.UI.Xaml.Data">
<Page.Resources>
<CollectionViewSource x:Name="ContactsCVS" IsSourceGrouped="True" />
<DataTemplate x:Key="ZoomedInTemplate" x:DataType="data:Contact">
<StackPanel Margin="20,0,0,0">
<TextBlock Text="{x:Bind Name}" />
<TextBlock Text="{x:Bind Position}" TextWrapping="Wrap" HorizontalAlignment="Left" Width="300" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="ZoomedInGroupHeaderTemplate" x:DataType="data:GroupInfoList">
<TextBlock Text="{x:Bind Key}"/>
</DataTemplate>
<DataTemplate x:Key="ZoomedOutTemplate" x:DataType="wuxdata:ICollectionViewGroup">
<TextBlock Text="{x:Bind Group.(data:GroupInfoList.Key)}" TextWrapping="Wrap"/>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<SemanticZoom x:Name="Control1" Height="500">
<SemanticZoom.ZoomedInView>
<GridView ItemsSource="{x:Bind ContactsCVS.View,Mode=OneWay}" ScrollViewer.IsHorizontalScrollChainingEnabled="False" SelectionMode="None"
ItemTemplate="{StaticResource ZoomedInTemplate}">
<GridView.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource ZoomedInGroupHeaderTemplate}" />
</GridView.GroupStyle>
</GridView>
</SemanticZoom.ZoomedInView>
<SemanticZoom.ZoomedOutView>
<ListView ItemsSource="{x:Bind ContactsCVS.View.CollectionGroups}" SelectionMode="None" ItemTemplate="{StaticResource ZoomedOutTemplate}" />
</SemanticZoom.ZoomedOutView>
</SemanticZoom>
</StackPanel>
</Grid>

How to hide top part of hamburger menu in the XAML Navigation Sample?

In the Windows UWP XAML Navigation sample from git hub, how can you hide the very top part of the hamburger menu flyout that obscures the section title?
Currently it renders like this so there is a strip that hides the section title of the page.
How can I get it to look like this? So the Section title is not obscured when I open the menu.
I tried playing with the z-index of the page header, but it had no effect. The hamburger menu always renders over top everything else.
Just check the Microsoft weather app for windows 10, I think it's more like there is a region out of the SplitView control, which is to hold like "hamburger button", "back button", "commandbar", and "AutoSuggestBox".
Here I wrote a sample:
<Page.Resources>
<local:BoolToVisiableConverter x:Key="visiblecvt" />
<local:BackgroundConverter x:Key="backgroundcvt" />
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="15*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="{Binding ElementName=listmenu, Path=SelectedItem.MenuText, Converter={StaticResource backgroundcvt}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<Button BorderThickness="0" Background="LightBlue" Click="Button_Click_Pane" Grid.Column="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Button.Content>
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="24" />
</Button.Content>
</Button>
<Button BorderThickness="0" Background="Transparent" Click="Button_Click_Back" Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Button.Content>
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="24" />
</Button.Content>
</Button>
<TextBlock FontSize="24" Grid.Column="2" x:Name="title" VerticalAlignment="Center" Text="{Binding ElementName=listmenu, Path=SelectedItem.MenuText}" />
<CommandBar Grid.Column="3" Background="Transparent" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Visibility="{Binding ElementName=title, Path=Text, Converter={StaticResource visiblecvt}}">
<CommandBar.Content>
<Grid />
</CommandBar.Content>
<AppBarButton Icon="Accept" FontSize="24" Label="Accept" />
<AppBarButton Icon="Cancel" FontSize="24" Label="Cancel" />
</CommandBar>
<AutoSuggestBox Grid.Column="4" VerticalAlignment="Center" HorizontalAlignment="Stretch" IsSuggestionListOpen="True" />
</Grid>
<SplitView Grid.Row="1" x:Name="RootSpiltView" OpenPaneLength="300" CompactPaneLength="50" DisplayMode="CompactOverlay">
<SplitView.Pane>
<ListView x:Name="listmenu" ItemsSource="{x:Bind menu}" SelectionChanged="ListView_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding MenuIcon}" FontFamily="Segoe MDL2 Assets" FontSize="24" VerticalAlignment="Center" />
<TextBlock Text="{Binding MenuText}" Margin="15" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</SplitView.Pane>
<SplitView.Content>
<Frame x:Name="splitviewContent" Navigated="splitviewContent_Navigated" />
</SplitView.Content>
</SplitView>
</Grid>
code behind:
private ObservableCollection<NavigationItem> menu = new ObservableCollection<NavigationItem>();
public MainPage()
{
this.InitializeComponent();
this.Loaded += MainPage_Loaded;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
menu.Clear();
menu.Add(new NavigationItem { PageLink = typeof(Page1), MenuText = typeof(Page1).Name, MenuIcon = "\xE715" });
menu.Add(new NavigationItem { PageLink = typeof(Page2), MenuText = typeof(Page2).Name, MenuIcon = "\xE716" });
menu.Add(new NavigationItem { PageLink = typeof(Page3), MenuText = typeof(Page3).Name, MenuIcon = "\xE722" });
menu.Add(new NavigationItem { PageLink = typeof(Page4), MenuText = typeof(Page4).Name, MenuIcon = "\xE72D" });
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
listmenu.SelectedIndex = 0;
}
private void Button_Click_Pane(object sender, RoutedEventArgs e)
{
this.RootSpiltView.IsPaneOpen = !this.RootSpiltView.IsPaneOpen;
}
private void Button_Click_Back(object sender, RoutedEventArgs e)
{
if (splitviewContent.CanGoBack)
{
splitviewContent.GoBack();
}
}
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var naviitem = listmenu.SelectedItem as NavigationItem;
splitviewContent.Navigate(naviitem.PageLink);
}
private void splitviewContent_Navigated(object sender, NavigationEventArgs e)
{
var page = splitviewContent.CurrentSourcePageType.Name;
switch (page)
{
case "Page1":
listmenu.SelectedIndex = 0;
break;
case "Page2":
listmenu.SelectedIndex = 1;
break;
case "Page3":
listmenu.SelectedIndex = 2;
break;
case "Page4":
listmenu.SelectedIndex = 3;
break;
}
}
The NavigationItem class and two converters:
public class NavigationItem
{
public string MenuIcon { get; set; }
public string MenuText { get; set; }
public Type PageLink { get; set; }
}
public class BoolToVisiableConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var text = (string)value;
if (text == "Page1")
{
return Visibility.Visible;
}
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
public class BackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var text = (string)value;
if (text == "Page1")
{
return "#FFFFC0CB";
}
return "#00000000";
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
I didn't follow to the official XAML Navigation sample to wrote this code, here my sample renders like this:
#Henk Holterman's comment also makes sense. In the official sample, the title is part of the page content. For different page, the title may have different size. But in Weather app, the title is separated from the content, so it will be easy to achieve.

XAML Gridview to add an item directly

I successfully coded an XAML Gridview to show list of items.
However, I want to add an [+(ADD ITEM)] button at the end of the Gridview.
The ADD button has should have a custom template (at least a default button) which is different from the content item.
My XAML source is below:
<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemsGridView"
AutomationProperties.Name="Items"
TabIndex="1"
Grid.RowSpan="2"
Padding="116,136,116,46"
ItemsSource="{Binding Source={StaticResource DataSource}}"
SelectionMode="None"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick">
<GridView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}">
<StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
<TextBlock Text="{Binding Subject}" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource BaseTextBlockStyle}" Height="60" Margin="15,0,15,0" FontWeight="SemiBold"/>
<TextBlock Text="{Binding TargetDate}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource BaseTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10" FontSize="12"/>
</StackPanel>
</Border>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<!--
Something like that..
<Button Content="+" x:Name="btnAdd" />
-->
</GridView>
And, how can I add a ADD button(grid item) to XAML? thanks
You can achieve that by using a DataTemplateSelector, basically what you need to do is :
define another class that will represent the GridView "addItem"
public class GridItem
{
public String Subject { get; set; }
public String TargetDate { get; set; }
}
public class AddGridItem : GridItem
{
public bool IsGridItem { get; set; }
}
Make sure that your GridView's ItemSource collection has always an AddGridItem in it
private ObservableCollection<GridItem> _gridItems =new ObservableCollection<GridItem>()
{
new GridItem()
{
Subject = "Subject1",
TargetDate = "TargetDate"
},new GridItem()
{
Subject = "Subject2",
TargetDate = "TargetDate"
},new GridItem()
{
Subject = "Subject3",
TargetDate = "TargetDate"
},new AddGridItem()
{
IsGridItem = true
}
};
public ObservableCollection<GridItem> GridItems
{
get
{
return _gridItems;
}
set
{
if (_gridItems == value)
{
return;
}
_gridItems = value;
}
}
Create a DataTemplateSelector class that will return the appropriate DataTemplate based on the Item type
public class MyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate RegularTemplate { get; set; }
public DataTemplate AddTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item,
DependencyObject container)
{
if (item is AddGridItem)
return AddTemplate;
if (item is GridItem)
return RegularTemplate;
return base.SelectTemplateCore(item, container);
}
}
Define your dataTempaltes and a DataTemplateSelector as staticresources to use them in your GridView
<Page.Resources>
<DataTemplate x:Key="RegularTemplate">
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<Border BorderThickness="3" BorderBrush="White">
<StackPanel VerticalAlignment="Bottom" Background="LightSkyBlue">
<TextBlock Text="{Binding Subject}" Style="{StaticResource BaseTextBlockStyle}" Height="60" Margin="15,0,15,0" FontWeight="SemiBold"/>
<TextBlock Text="{Binding TargetDate}" Style="{StaticResource BaseTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10" FontSize="12"/>
</StackPanel>
</Border>
</Grid>
</DataTemplate>
<DataTemplate x:Key="AddItemTemplate">
<Border BorderThickness="3" BorderBrush="White" Background="DodgerBlue">
<FontIcon Glyph="" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White"/>
</Border>
</DataTemplate>
<local:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
RegularTemplate="{StaticResource RegularTemplate}"
AddTemplate="{StaticResource AddItemTemplate}">
</local:MyDataTemplateSelector>
</Page.Resources>
<Grid>
<GridView ItemsSource="{Binding GridItems}" ItemTemplateSelector="{StaticResource MyDataTemplateSelector}">
</GridView>
</Grid>

windows store app how to get back values from databinded usercontroles

how can i get back values from data binder view elements
am using a list view and data binded it to collection
<ListView.Resources>
<DataTemplate x:Key="DataTemplate1">
<Grid Height="20" Width="100" Background="#FFF5F3F3" Tapped="Grid_Tapped">
<TextBlock Text="{Binding Name}" Foreground="#FF0E0303"/>
<TextBlock Text="{Binding Age}" Foreground="#FF0E0303"/>
</Grid>
</DataTemplate>
now what i want is get the values back at gridtapped event
Try this
<ListView x:Name="lv" IsItemClickEnabled="True" ItemClick="lv_ItemClick_1">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Height="20" Width="100" Background="#FFF5F3F3">
<TextBlock Text="{Binding Name}" Foreground="#FF0E0303"/>
<TextBlock Text="{Binding Age}" Foreground="#FF0E0303"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
lv.ItemsSource = new List<Person>
{
new Person("Charles", 25),
new Person("Mark", 27),
new Person("John", 22),
};
}
private void lv_ItemClick_1(object sender, ItemClickEventArgs e)
{
var objPerson = (Person)e.ClickedItem;
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
}

MVVM WCF Entity as Model... How to implement propertychange notification in the view model when using Entity as your model

I am implementing an MVVM Pattern using Entity as my model... When I instantiate the Model in the setter I add a propertychanged handler to the object to capture the field changes within the entity object...
When I step through code I find that after I modify the field within the object it is firing the Property Change event multiple times...
It has led me to believe that I have done something wrong...
I want to use the entity as my model as I do not want to recreate the object as an abstacted object...
Can any find any fault in the code base below that would cause the SelectedCompany.PropertyChanged to fire more then once when the datagrid field is modified...
I was expecting that that the property changed event would only fire once and am a bit perplexed as to why it fires multiple times...
Was it wrong to add the propertyChange event in the Setter...
Here is the ViewModel...
public class CompanyMaintenanceVM : INotifyPropertyChanged
{
private ServiceHandler _serviceHandler = new ServiceHandler();
private bool _ignorePropertyChange = false; //by default we will execute on every property change...
public CompanyMaintenanceVM()
{
_companyList = new ObservableCollection<Company>(_serviceHandler.GetCompanies().ToList());
_selectedCompany = _companyList.First();
UpdateCommand = new RelayCommand(Update) { IsEnabled = true };
SearchCommand = new RelayCommand(Search) { IsEnabled = true };
_companyTypeList = new ObservableCollection<CompanyType>(_serviceHandler.GetCompanyTypes().ToList());
}
private string _selectedKey;
public string SelectedKey
{
get { return _selectedKey; }
set
{
if (_selectedKey != value)
{
_selectedKey = value;
OnPropertyChanged("SelectedKey");
}
}
}
private Company _selectedCompany = new Company();
public Company SelectedCompany
{
get { return _selectedCompany; }
set
{
if (_selectedCompany != value)
{
_selectedCompany = value;
OnPropertyChanged("SelectedCompany");
SelectedCompany.PropertyChanged += new PropertyChangedEventHandler(SelectedCompany_PropertyChanged);
}
}
}
private ObservableCollection<Company> _companyList;
public ObservableCollection<Company> CompanyList
{
get { return _companyList; }
set
{
_companyList = value;
OnPropertyChanged("CompanyList");
}
}
private ObservableCollection<CompanyType> _companyTypeList;
public ObservableCollection<CompanyType> CompanyTypeList
{
get { return _companyTypeList; }
set { _companyTypeList = value; }
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
switch (propertyName)
{
case "SelectedKey":
if (_ignorePropertyChange == false)
{
SelectedKeyChanged();
}
_ignorePropertyChange = false;
break;
case "SelectedCompany":
_ignorePropertyChange = true;
SelectedKey = SelectedCompany.CompanyID;
break;
}
}
void SelectedCompany_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
//
}
#endregion
private void SelectedKeyChanged()
{
var companies = _serviceHandler.GetCompanyByID(SelectedKey);
if (companies.FirstOrDefault() != null)
{
CompanyList = new ObservableCollection<Company>(companies);
SelectedCompany = CompanyList.First();
}
else
{
MessageBox.Show("No Company Record Exsists Matching CompanyID " + _selectedKey);
}
}
private ICommand _updateCommand;
public ICommand UpdateCommand
{
get
{
if (_updateCommand == null)
_updateCommand = new Updater();
return _updateCommand;
}
set
{
_updateCommand = value;
}
}
private class Updater : ICommand
{
#region ICommand Members
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(Object parameter)
{
}
#endregion
}
private void Update()
{
_serviceHandler.UpdateRepository(SelectedCompany);
_serviceHandler.CommitRepository();
}
private ICommand _searchCommand;
public ICommand SearchCommand
{
get
{
if (_searchCommand == null)
_searchCommand = new Searcher();
return _searchCommand;
}
set
{
_searchCommand = value;
}
}
private class Searcher : ICommand
{
#region ICommand Members
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(Object parameter)
{
}
#endregion
}
private void Search()
{
}
}
Here is the XAML...
<Window x:Class="XERP.Client.WPF.CompanyMaintenance.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Company Maintenance" Height="800" Width="600">
<Grid>
<Grid.Resources>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="422*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="156*"></ColumnDefinition>
<ColumnDefinition Width="422*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Center" Grid.Column="1" Text="Company Maintenance Form"
FontSize="13"
Margin="130,3,129,5"></TextBlock>
<Menu IsMainMenu="True" Grid.ColumnSpan="2" Margin="2,2,370,2" Width="180">
<MenuItem Header="_File" >
<MenuItem Header="_New" Command="New">
</MenuItem>
<MenuItem Header="_Save"
IsCheckable="True"
Command="{Binding UpdateCommand}" Click="SaveMenuItem_Click">
</MenuItem>
<MenuItem Header="_Exit" Command="Close">
</MenuItem>
</MenuItem>
<MenuItem Header="_Edit">
<MenuItem Header="_Cut" Command="Cut">
</MenuItem>
<MenuItem Header="_Copy" Command="Copy">
</MenuItem>
<MenuItem Header="_Paste" Command="Paste">
</MenuItem>
</MenuItem>
<MenuItem Header="_Tools" />
<MenuItem Header="_Actions" />
<MenuItem Header="_Help" />
</Menu>
<GridSplitter Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right" Width="4" Background="Yellow"/>
<ListView Grid.Row="1" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5"
ItemsSource="{Binding CompanyList}"
SelectedItem="{Binding SelectedCompany, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectionMode="Single"
IsSynchronizedWithCurrentItem="True"
>
<ListView.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding Path=CompanyID, Mode=TwoWay}" Margin="5"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<TabControl Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<TabItem Header="Detail">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="46"></RowDefinition>
<RowDefinition Height="657*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="165*"></ColumnDefinition>
<ColumnDefinition Width="246*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Orientation="Horizontal" Grid.Row="0" Grid.ColumnSpan="2">
<Button Width="100" Height="20" Margin="10"
Command="{Binding SearchCommand}">Company...</Button>
<TextBox Width="100" Height="20" Margin=" 10"
Text="{Binding Path=SelectedKey, Mode=TwoWay}"
/>
</StackPanel>
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Orientation="Vertical" Grid.Row="1" Grid.Column="0">
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Top" Margin="8">Name:</TextBlock>
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Top" Margin="8">Description:</TextBlock>
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Top" Margin="8">Type:</TextBlock>
</StackPanel>
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Orientation="Vertical" Grid.Row="1" Grid.Column="1">
<TextBox HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5" Width="200"
Text="{Binding Path=SelectedCompany.Name, Mode=TwoWay}"
/>
<TextBox
HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5" Width="200"
Text="{Binding Path=SelectedCompany.Description, Mode=TwoWay}"
/>
<ComboBox HorizontalAlignment="Left" Width="200" Margin="5"
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CompanyTypeList, Mode=TwoWay}"
DisplayMemberPath="Type"
SelectedValuePath="CompanyTypeID"
SelectedValue="{Binding Path=SelectedCompany.CompanyTypeID, Mode=TwoWay}"/>
<TextBox Height="23" Name="ghost" Width="0" />
</StackPanel>
</Grid>
</TabItem>
<TabItem Header="List" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid>
<DataGrid AutoGenerateColumns="False"
ItemsSource="{Binding CompanyList}"
SelectedItem="{Binding SelectedCompany, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectionMode="Single"
IsSynchronizedWithCurrentItem="True"
>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding CompanyID, Mode=TwoWay}"
Header="ID" Width="auto" IsReadOnly="True"/>
<DataGridTextColumn Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
Header="Name" Width="Auto"/>
<DataGridTextColumn Binding="{Binding Description, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
Header="Description" Width="Auto"/>
<DataGridComboBoxColumn Header="Type" Width="Auto"
SelectedValueBinding ="{Binding CompanyTypeID, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
DisplayMemberPath="Type"
SelectedValuePath="CompanyTypeID">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CompanyTypeList, Mode=TwoWay}"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CompanyTypeList, Mode=TwoWay}"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
</DataGrid>
<TextBox Height="23" Name="ghost2" Width="0" />
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>
be aware of using selecteditem with twoway binding AND IsSynchronizedWithCurrentItem="True" - maybe there you get your roundtrips.
and what your cause for the following?
if (_selectedCompany != value)
{
_selectedCompany = value;
OnPropertyChanged("SelectedCompany");
SelectedCompany.PropertyChanged += new PropertyChangedEventHandler(SelectedCompany_PropertyChanged); //<-- whats that?
}
and why you do this?
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
switch (propertyName)//why you do this?
{
case "SelectedKey":
if (_ignorePropertyChange == false)
{
SelectedKeyChanged();
}
_ignorePropertyChange = false;
break;
case "SelectedCompany":
_ignorePropertyChange = true;
SelectedKey = SelectedCompany.CompanyID;
break;
}
}