How can I open my default webbrowser in WPF? - c#

I am trying to create a custom command called WebBrowser which will open my default webbrowser and go to google.com when I click on it. So far I only made the exit command, and I a really stuck how to implement this command. Any help would be amazing.
The XAML is:
<Window x:Class="WpfTutorialSamples.Commands.CustomCommandSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self="clr-namespace:WpfTutorialSamples.Commands"
Title="CustomCommandSample" Height="150" Width="200">
<Window.CommandBindings>
<CommandBinding Command="self:CustomCommands.Exit" CanExecute="ExitCommand_CanExecute" Executed="ExitCommand_Executed" />
</Window.CommandBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Menu>
<MenuItem Header="My Command">
<MenuItem Command="self:CustomCommands.Exit" />
</MenuItem>
</Menu>
<StackPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Window>
The code-behind is:
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.Navigation;
using System.Windows.Shapes;
namespace WpfTutorialSamples.Commands
{
public partial class CustomCommandSample : Window
{
public CustomCommandSample()
{
InitializeComponent();
}
private void ExitCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void ExitCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
Application.Current.Shutdown();
}
}
public static class CustomCommands
{
public static readonly RoutedUICommand Exit = new RoutedUICommand
(
"Exit",
"Exit",
typeof(CustomCommands),
new InputGestureCollection()
{
new KeyGesture(Key.F4, ModifierKeys.Alt)
}
);
}
}
I am trying to make it look like this:
http://i.stack.imgur.com/k8ezB.png

You need a command which starts a new process and gives it as an argument a URL. I am using DelegateCommand here but you can use any custom ICommand you already have:
public DelegateCommand StartChromeCommand = new DelegateCommand(OnStartChrome);
private void OnStartChrome()
{
var process = new Process(new ProcessStartInfo {Arguments = #"http://www.google.com"});
process.Start();
}

Related

Return Value to the MainWindows [duplicate]

This question already has answers here:
Passing parameters between viewmodels
(2 answers)
Closed 8 years ago.
Goal:
When you click one of the rows in the lstView_bbb (in Test.xaml), the return value shall be return to the class MainWindow (MainWindow.xaml). And then, the Test.xaml shall be closed.
Problem:
I tried finding a solution that data of "_a" from row shall be transferred to the MainWIndow but it didn't go so well due to performance issue. I want to make it more efficient.
Information:
*I'm using WPF with VS 2013
*The return value is "_a" to the class MainWIndow.xaml
<Window x:Class="WpfApplication1.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>
<Button x:Name="btn_test" Content="Test" HorizontalAlignment="Left" Margin="348,240,0,0" VerticalAlignment="Top" Width="75" Click="btn_test_Click"/>
</Grid>
</Window>
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.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private List<aaa> _myList_aaa;
private void btn_test_Click(object sender, RoutedEventArgs e)
{
_myList_aaa = new List<aaa>();
for (int a = 1; a <= 5; a++)
{
aaa myaaa = new aaa();
myaaa._a = a;
myaaa._city = "New Yor";
myaaa._name = "jj jj jj";
_myList_aaa.Add(myaaa);
}
Test myTest = new Test(_myList_aaa);
myTest.ShowDialog();
}
}
public class aaa
{
public int _a { get; set; }
public string _name { get; set; }
public string _city { get; set; }
}
}
---------------------------------------
<Window x:Class="WpfApplication1.Test"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test" Height="300" Width="300">
<Grid Background="#FFE5E5E5">
<ListView x:Name="lstView_bbb" SelectionMode="Single" ItemsSource="{Binding}" HorizontalAlignment="Left" Height="111" Margin="35,67,0,0" VerticalAlignment="Top" Width="222">
<ListView.View>
<GridView>
<GridViewColumn Header="name" Width="auto" DisplayMemberBinding="{Binding Path=_name}" TextBlock.TextAlignment="Left" />
<GridViewColumn Header="city" Width="auto" DisplayMemberBinding="{Binding Path=_city}" TextBlock.TextAlignment="Center" />
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
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;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Test.xaml
/// </summary>
public partial class Test : Window
{
public Test(IList<aaa> pAAA)
{
InitializeComponent();
lstView_bbb.DataContext = pAAA;
}
}
}
The easiest way is to create a property in Test:
class Test
{
public aaa SelectedItem
{
get
{
return lstView_bbb.SelectedItems[0] as aaa;
}
}
The best way is to use a ViewModel. Assign it to Test and use the same ViewModel in you other form to get the selected value.
Read the related MSDN article.

WPF databinding cannot get data

I am writting a login window using WPF and C#,but got stuck when I attempted to retrive username from the TextBox.The class property which I bind to the TextBox always get a null value,and I cannot figure out why.
MainWindow.xaml
<Window x:Class="Databinding.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>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="256*"/>
<ColumnDefinition Width="261*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Username" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" FontSize="20"/>
<Label Grid.Row="1" Grid.Column="0" Content="Password" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" FontSize="20"/>
<Button Content="Confirm" Click="Confirm_Click" IsDefault="True" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" FontSize="20"/>
<Button Content="Cancel" Click="Cancel_Click" IsCancel="True" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" FontSize="20"/>
<TextBox x:Name="TextUsername" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" Margin="0,0,0,0" TextWrapping="Wrap" VerticalAlignment="Stretch" ToolTip="Enter your username"/>
<PasswordBox x:Name="Password" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" ToolTip="Enter your password"/>
</Grid>
MainWindow.xaml.cs
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.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
namespace Databinding
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Confirm_Click(object sender, RoutedEventArgs e)
{
Login LoginInfo = new Login();
Binding bindingLogin = new Binding();
bindingLogin.Source = LoginInfo;
bindingLogin.Path = new PropertyPath("Username");
bindingLogin.Mode = BindingMode.TwoWay;
bindingLogin.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(this.TextUsername, TextBox.TextProperty, bindingLogin);
if(LoginInfo.Username=="admin" && this.Password.Password=="admin")
{
MessageBox.Show("Welcome!","Login Status");
}
else
{
MessageBox.Show("Something is wrong!","Login Status");
}
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
public class Login:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string username;
public string Username
{
get
{
return username;
}
set
{
username = value;
if(this.PropertyChanged!=null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Username"));
}
}
}
}
}
I know databinding is not a wise option in this case,and I can get things done more efficently by just using
string Username = this.TextUsername.Text
Anyway,this is a some demo,and I have to use databinding in my project.What's wrong with my code?
At the point you attach your binding, Login.Username is null, and since the binding is two way WPF will update your textbox to null to match.
Bindings are supposed to be active all the time, and declared in the XAML, rather than bound at the point you want data. You are defeating the object of using bindings. Like you say, it would be far easier to just grab the text directly if you are going to do it explicitly.
The problem is when user entering/changing Text in the TextUsername, your binding is not there yet, (your binding will only be there after the Confirm_Click, and will be reset with each Confirm_Click) so you need to move it to the constructor.
namespace Databinding
{
public partial class MainWindow : Window
{
Login LoginInfo;
public MainWindow()
{
InitializeComponent();
LoginInfo = new Login();
Binding bindingLogin = new Binding();
bindingLogin.Source = LoginInfo;
bindingLogin.Path = new PropertyPath("Username");
bindingLogin.Mode = BindingMode.TwoWay;
bindingLogin.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(this.TextUsername, TextBox.TextProperty, bindingLogin);
}
//... rest
}
}
And you could easily apply the binding in XAML, and avoid all of these code behind if you can set the DataContext of your window correctly e.g.:
<TextBox x:Name="TextUsername" Text="{Binding Username}" ..../>
The below code will works, not sure if it's a good practice thou:
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.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
namespace Databinding
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Login LoginInfo;
Binding bindingLogin;
public MainWindow()
{
InitializeComponent();
LoginInfo = new Login();
bindingLogin = new Binding();
bindingLogin.Source = LoginInfo;
bindingLogin.Path = new PropertyPath("Username");
bindingLogin.Mode = BindingMode.TwoWay;
bindingLogin.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
}
private void Confirm_Click(object sender, RoutedEventArgs e)
{
BindingOperations.SetBinding(this.TextUsername, TextBox.TextProperty, bindingLogin);
if(LoginInfo.Username=="admin" && this.Password.Password=="admin")
{
MessageBox.Show("Welcome!","Login Status");
}
else
{
MessageBox.Show("Something is wrong!","Login Status");
}
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
public class Login:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string username;
public string Username
{
get
{
return username;
}
set
{
username = value;
if(this.PropertyChanged!=null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Username"));
}
}
}
}
}

WPF Custom control in WinForms with floating precision size

I was wondering is it possible to create a panel-like control in wpf, and another wpf custom control that will be the child of this panel, all in WinForms application. And then, would it be possible to set the custom control's size in float?
Also would I be able to rotate that custom control?
Thanks in advance
You will need to use the System.Windows.Forms.Integration NameSpace, more specifically the ElementHost Control, that will allow you to embed a WPF Control in Winforms.
This is a quick and simple demonstration of changing the WPF UserControls Child UserControls Size and Location. I will leave the animation to you.
Main Winform Form
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
ElementHost host;
WpfControlLibrary1.UserControl1 uc;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
host = new ElementHost();
host.Dock = DockStyle.Top;
uc = new WpfControlLibrary1.UserControl1();
host.Child = uc;
this.Controls.Add(host);
}
private void button1_Click(object sender, EventArgs e)
{
uc.SetChildLocation = new System.Windows.Point(uc.SetChildLocation.X + 25.5, uc.SetChildLocation.Y + 10.2);
}
private void button2_Click(object sender, EventArgs e)
{
uc.SetChildSize = new System.Windows.Size(uc.SetChildSize.Width + .25, uc.SetChildSize.Height + .25);
}
}
}
UserControl1.xaml
<UserControl x:Class="WpfControlLibrary1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Background="Red" xmlns:my="clr-namespace:WpfControlLibrary1">
<Canvas>
<my:UserControl2 HorizontalAlignment="Center" x:Name="userControl21" VerticalAlignment="Center" Canvas.Left="0" Canvas.Top="0" />
</Canvas>
</UserControl>
UserControl1.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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.Navigation;
using System.Windows.Shapes;
namespace WpfControlLibrary1
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public Point SetChildLocation
{
get
{
return new Point(Canvas.GetLeft(userControl21), Canvas.GetTop(userControl21));
}
set
{
Canvas.SetLeft(userControl21, value.X);
Canvas.SetTop(userControl21, value.Y);
}
}
public Size SetChildSize
{
get
{
return new Size(userControl21.ActualWidth, userControl21.ActualHeight);
}
set
{
userControl21.Width = value.Width;
userControl21.Height = value.Height;
}
}
}
}
UserControl2.xaml
<UserControl x:Class="WpfControlLibrary1.UserControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" SizeChanged="UserControl_SizeChanged">
<Grid>
<Rectangle x:Name="rect" Fill="Blue" Height="40" Width="120"></Rectangle>
</Grid>
</UserControl>
UserControl2.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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.Navigation;
using System.Windows.Shapes;
namespace WpfControlLibrary1
{
/// <summary>
/// Interaction logic for UserControl2.xaml
/// </summary>
public partial class UserControl2 : UserControl
{
public UserControl2()
{
InitializeComponent();
}
private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
{
rect.Width = e.NewSize.Width;
rect.Height = e.NewSize.Height;
}
}
}

WPF Populating list, assigning on-click event handler with custom variables to pass

I'm populating a listBox, Each list item has a button.
I've got it populating text in to the list, but I'd like each button to have the correct event handler and the house number to be passed to it.
Here's the XAML code:
<Window x:Class="WpfApplication1.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" Loaded="Window_Loaded" Background="#FFCBCBCB">
<Grid>
<Label Content="Welcome to the house manager" Height="28" HorizontalAlignment="Left" Margin="20,12,0,0" Name="label1" VerticalAlignment="Top" />
<ListBox Height="253" HorizontalAlignment="Left" Margin="10,46,0,0" VerticalAlignment="Top" Width="481" x:Name="houseList">
<ListBox.ItemTemplate>
<DataTemplate DataType="house">
<Button Click="choose_house(HOUSE NUMBER HERE)" Background="#FFBEBEBE" BorderThickness="0" Focusable="True" Width="459" BorderBrush="White" Padding="0">
<StackPanel Orientation="Vertical" Width="400" VerticalAlignment="Stretch">
<TextBlock Margin="0,5,0,0" Text="{Binding street}" HorizontalAlignment="Left" />
<TextBlock Margin="0,5,0,0" Text="{Binding postCode}" HorizontalAlignment="Left" />
</StackPanel>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
Here's the code which populates the list at the moment:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
List<house> houseAddresses = new List<house>();
// Create a new house
for (var i = 1; i <= 10; i++)
{
house newHouse = new house();
newHouse.street = i + " Scale Hall Lane";
newHouse.postCode = "PR4 3TL";
newHouse.houseNumber = i;
houseAddresses.Add(newHouse);
}
// Go through each house and add them to the list
foreach (house houses in houseAddresses)
{
houseList.Items.Add(houses);
}
}
private void choose_house(object sender, RoutedEventArgs e)
{
MessageBox.Show("Clicked");
}
}
}
Here's my house class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WpfApplication1
{
class house
{
public string street { get; set; }
public string postCode { get; set; }
public int houseNumber { get; set; }
}
}
I've put Click="choose_house(HOUSE NUMBER HERE)" in the code on the button where the code would have the correct event handler.
Either cast your sender as a Button and get it's DataContext, or use a Command and bind the CommandParameter to the HouseNumber
private void choose_house(object sender, RoutedEventArgs e)
{
var ctrl = sender as Button;
var h = ctrl.DataContext as house; // Please capitalize your classes! :)
MessageBox.Show(h.houseNumber);
}
or
<Button Command="{Binding Path=DataContext.ChooseHouseCommand,
RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
CommandParameter="{Binding houseNumber}" ... />
What you can do on the click handler is:
private void choose_house(object sender, RoutedEventArgs e)
{
var button = sender as Button;
if (button != null)
{
var yourObject = button.DataContext as house;
if (yourObject != null)
{
//do stuff with your button
}
}
}

WPF Databinding Question

I've written a very short app in which I'm trying to achieve the following : have the CheckBox change its state from code. I've wired up the INotifyPropertyChanged interface and was expecting to see some results but apparently the app does nothing. Is there something wrong with the databinding?
Window1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
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.Navigation;
using System.Windows.Shapes;
using System.Threading;
namespace WpfTEST
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window, INotifyPropertyChanged
{
public Window1()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Window1_Loaded);
this.PropertyChanged += new PropertyChangedEventHandler(Window1_PropertyChanged);
}
public bool Flag
{
get { return m_flag; }
set
{
m_flag = value;
OnPropertyChanged("Flag");
}
}
private bool m_flag = false;
void Window1_Loaded(object sender, RoutedEventArgs e)
{
this.m_cbox.DataContext = this;
for (int i = 0; i < 1000; i++)
{
Flag = (i % 2 == 0);
Thread.Sleep(200);
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
void Window1_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
}
#endregion
}
}
Window1.xaml
<Window x:Class="WpfTEST.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" x:Name="window">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0.5*" />
<RowDefinition Height="0.5*" />
</Grid.RowDefinitions>
<CheckBox x:Name="m_cbox" Content="Let's see what happens" Grid.Row="2" Grid.Column="2" Grid.RowSpan="1" Grid.ColumnSpan="1" IsChecked="{Binding Path=Flag, ElementName=window, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</Window>
The only real problem I see with your code is the sleep loop in Loaded. That causes the UI thread to go unresponsive for the duration of the loop, since you're putting the UI thread into a blocked state.
There's a better way to test if you can change the flag from code and have your binding fire. Add a button to the window, hook up a click handler to the button, and in that click handler, toggle Flag -- I made those modifications to your original code (and removed the sleep loop), clicking on the button toggles the checkbox's state in the fashion you seem to desire.
<Window x:Class="WpfTEST.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" x:Name="window">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0.5*" />
<RowDefinition Height="0.5*" />
</Grid.RowDefinitions>
<!-- I added this button: -->
<Button Click="Button_Click" Grid.Row="0" Grid.Column="0"/>
<CheckBox x:Name="m_cbox" Content="Let's see what happens" Grid.Row="2" Grid.Column="2" Grid.RowSpan="1" Grid.ColumnSpan="1" IsChecked="{Binding Path=Flag, ElementName=window, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</Window>
and in code behind:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
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.Navigation;
using System.Windows.Shapes;
using System.Threading;
namespace WpfTEST {
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window, INotifyPropertyChanged {
public Window1() {
InitializeComponent();
this.Loaded += new RoutedEventHandler(Window1_Loaded);
this.PropertyChanged += new PropertyChangedEventHandler(Window1_PropertyChanged);
}
public bool Flag {
get { return m_flag; }
set {
m_flag = value;
OnPropertyChanged("Flag");
}
}
private bool m_flag = false;
void Window1_Loaded( object sender, RoutedEventArgs e ) {
this.m_cbox.DataContext = this;
Flag = false;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged( string name ) {
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
void Window1_PropertyChanged( object sender, PropertyChangedEventArgs e ) {
}
#endregion
private void Button_Click( object sender, RoutedEventArgs e ) {
Flag = !Flag;
}
}
}
Other than the above modifications to add the button and its click handler, and remove that sleep loop, I made no modifications to your original code (although you could streamline it a bit).
That will only work if your Flag property is a dependency property. To get this working in the simplest way i can think of i would do the following :
change your binding to be :
IsChecked="{Binding Path=Flag,Mode=TwoWay}"
and in your constructor in your code behind do this :
DataContext = this;
or in XAML
DataContext="{Binding RelativeSource={RelativeSource self}}"
Note : Flag does not need to be a dependency property if you are setting the datacontext to be the window.

Categories