- Details
- Written by: Stanko Milosev
- Category: WPF
- Hits: 10360
I was playing with TabControl, and I tried to implement SelectionChange event of TabControl.
So I did something like this:
XAML:
<Window x:Class="WpfApplication20.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <TabControl SelectionChanged="TabControl_SelectionChanged"> <TabItem Header="Test1"></TabItem> <TabItem Header="Test2"></TabItem> </TabControl> </Grid> </Window>
Code behind:
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e) { MessageBox.Show("test"); }
With that code I was receiving error:
Dispatcher processing has been suspended, but messages are still being processed.
Solution:
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(this.MyTest)); } private void MyTest() { MessageBox.Show("test"); }
It seems that problem is in multi thread... Because for example code like this:
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e) { // ... Get TabControl reference. var item = sender as TabControl; // ... Set Title to selected tab header. var selected = item.SelectedItem as TabItem; this.Title = selected.Header.ToString(); }
Works without problem.
- Details
- Written by: Stanko Milosev
- Category: WPF
- Hits: 5944
How to bind command to a button I explained here.
Here is my XAML:
<Window x:Class="UpdateBinding.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:viewModel="clr-namespace:UpdateBinding.ViewModel" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <viewModel:UpdateBindingViewModel x:Key="UpdateBindingBindingViewModel" /> </Window.Resources> <Grid DataContext="{StaticResource UpdateBindingBindingViewModel}"> <StackPanel> <TextBox Name="MyTextBox" Text="{Binding Ubm.Name}" VerticalAlignment="Top"/> <Button VerticalAlignment="Top" Command="{Binding OnButtonClick}">test</Button> </StackPanel> </Grid> </Window>
Command to update value looks like this:
public void UpdateBinding(object obj) { Ubm.Name = "Updated value"; OnPropertyChanged(() => this.Ubm); }
Part of code:
protected void OnPropertyChanged<T>(Expression<Func<T>> property) { if (this.PropertyChanged != null) { var mex = property.Body as MemberExpression; string name = mex.Member.Name; this.PropertyChanged(this, new PropertyChangedEventArgs(name)); } }
I took from here.
Also don't forget to implement INotifyPropertyChanged interface, in my case declaration of viewmodel looks like this:
public class UpdateBindingViewModel: INotifyPropertyChanged
Example application you can download from here.
---
2014-06-11 Update Just a short notice. If you implement interface by default (with resharper alt + enter :) ) then to use it, you have to write which property of class (view model) are you updating. Something like:
[NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); if (propertyName == "test") { MyHidden = !MyHidden; myContent = "Clicked!"; } } }
Where OnPropertyChanged is called like this:
OnPropertyChanged("MyHidden");
Obviously this example is not compatible with previous example :) I hope I will update this article soon...
---
2014-06-13 Another update
Check out following code:
namespace BooleanToVisibilityConverterExample.ViewModel { using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Input; using BooleanToVisibilityConverterExample.Annotations; public class BooleanToVisibilityConverterExampleViewModel: INotifyPropertyChanged { public ICommand OnClick { get; set; } public bool MyHidden { get; set; } public BooleanToVisibilityConverterExampleViewModel() { OnClick = new RelayCommand(ShowHide); MyHidden = true; } private void ShowHide(object obj) { MyHidden = !MyHidden; OnPropertyChanged("MyHidden"); } public event PropertyChangedEventHandler PropertyChanged; [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } }
Here notice lines:
MyHidden = !MyHidden; OnPropertyChanged("MyHidden");
With these lines I said that I want to update property MyHidden which is bounded to rectangle visibility. This update actually is coming from this article, and example you can download from here.
- Details
- Written by: Stanko Milosev
- Category: WPF
- Hits: 4684
I just want to show one more examples of binding.
Beside binding of TreeView to which I already gave an example here, there is another possibility of TreeView binding.
For this example I don't need model, so my view model looks like this:
public class ClassBinding { public List<string> MyTest { get { List<string> pom = new List<string>(); pom.Add("test"); return pom; } } public ClassBinding MyContextTest { get { return new ClassBinding(); } } }
My XAML for tree view binding looks like this:
<Grid> <TreeView DataContext="{Binding Path=MyContextTest}" ItemsSource="{Binding MyTest}"/> </Grid>
Notice line {Binding Path=MyContextTest} then notice that MyContextClass is property of the class ClassBinding.
Example project you can download from here.
This article I wrote with help of my colleague from ISE.
- Details
- Written by: Stanko Milosev
- Category: WPF
- Hits: 10043
So, idea was to have to listbox where one list box I will fill with data from MySQL, and in another with data from XML.
This is example is maybe not good, since I don't have model, I just wanted to play with autofac on a simplest possible way.
So here are my interfaces:
public interface IMyTree { List<string> Read(List<string> listMyElements); } public interface IReadMyTree { List<string> ReadXml(); List<string> ReadMySql(); }
Here is the class which will actually return
public class DoMytree : IMyTree { public List<string> Read(List<string> listMyElements) { return listMyElements; } }
Note that this class basically does nothing, that is because I don't have model, so I couldn't pass list of elements, for example, because structure is not same as structure from mySql.
Now, here is example of ReadMySql method:
public class MyReader : IReadMyTree { private readonly IMyTree _output; public MyReader(IMyTree output) { this._output = output; } public List<string> ReadMySql() { string MyConString = "SERVER=server;" + "DATABASE=db;" + "UID=user;" + "PASSWORD=pass;Convert Zero Datetime=True"; string sql = "select * from jos_categories"; try { var connection = new MySqlConnection(MyConString); var cmdSel = new MySqlCommand(sql, connection); connection.Open(); MySqlDataReader dataReader = cmdSel.ExecuteReader(); var pom = new List<string>(); while (dataReader.Read()) { object bugId = dataReader["title"]; pom.Add(bugId.ToString()); } return _output.Read(pom); } catch (Exception e) { MessageBox.Show("Error: " + e); } return null; } }
Note line: return _output.Read(pom); little bit of nonsense I agree :) I just wanted to follow dependency injection... This example is just for learning, remember ;)
Interesting thing to notice are lines:
var connection = new MySqlConnection(MyConString); var cmdSel = new MySqlCommand(sql, connection); connection.Open(); MySqlDataReader dataReader = cmdSel.ExecuteReader(); var pom = new List<string>(); while (dataReader.Read()) { object bugId = dataReader["title"]; pom.Add(bugId.ToString()); }
Here you can see how to fill list of strings from mySql, example how to connect to mySql you find here.
public class ReadMySqlTreeViewAutofacViewModel { public static List<string> ReadMySql() { var scope = MainWindow.Container.BeginLifetimeScope(); var writer = scope.Resolve<IReadMyTree>(); return writer.ReadMySql(); } public List<string> TreeMySqlViewModels { get; set; } public ReadMySqlTreeViewAutofacViewModel() { var builder = new ContainerBuilder(); builder.RegisterType<MyReader>().As<IReadMyTree>(); builder.RegisterType<DoMytree>().As<IMyTree>(); MainWindow.Container = builder.Build(); TreeMySqlViewModels = ReadMySql(); } }
XAML:
<Window x:Class="ReadXmlTreeViewAutofac.View.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib" xmlns:viewModel="clr-namespace:ReadXmlTreeViewAutofac.ViewModel" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <viewModel:TreeViewModel x:Key="TreeViewModel" /> <viewModel:ReadMySqlTreeViewAutofacViewModel x:Key="ReadMySqlTreeViewAutofacViewModel" /> </Window.Resources> <TabControl> <TabItem Header="Read from Xml"> <Grid DataContext="{StaticResource TreeViewModel}" OverridesDefaultStyle="True"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TreeView Grid.Row="0" Grid.Column="0" Name="TvXml" ItemsSource="{Binding Path=TreeXmlViewModels}"/> </Grid> </TabItem> <TabItem Header="Read from MySql"> <Grid OverridesDefaultStyle="True" DataContext="{StaticResource ReadMySqlTreeViewAutofacViewModel}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TreeView Grid.Row="0" Grid.Column="0" Name="TvMySql" ItemsSource="{Binding Path=TreeMySqlViewModels}"/> </Grid> </TabItem> </TabControl> </Window>
Things to notice in XAML are lines:
xmlns:viewModel="clr-namespace:ReadXmlTreeViewAutofac.ViewModel"
This is namespace which we will use, and lines:
<viewModel:TreeViewModel x:Key="TreeViewModel" />
<viewModel:ReadMySqlTreeViewAutofacViewModel x:Key="ReadMySqlTreeViewAutofacViewModel" />
These are classes which we will use to bind them with our trees, and finally tree binding:
<TreeView Grid.Row="0" Grid.Column="0" Name="TvXml" ItemsSource="{Binding Path=TreeXmlViewModels}"/>
Note that TreeXmlViewModels is property which I am registering it in autofac registration part, also note that I am preparing that property in line TreeXmlViewModels = ReadXml();
Example application you can download from here.
Github is here.