I have two WPF windows and i want to set the context to a ViewModel but if I write:
this.DataContext = new myViewModel()
in my second windows cs it doesn't work here is my code. i have tried to place a binding in the XAML and to connect the context but when i try to debug it all i get the error code this breakpoint will not get run.
BrowseDialog.xaml
<Window x:Class="TextalkApi.BrowseDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TextalkApi"
mc:Ignorable="d"
Title="BrowseDialog" Height="248.361" Width="427.459">
<Grid>
<Button Content="Browse" HorizontalAlignment="Left" Margin="267,11,0,0" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="FileDialog" HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" Text="{Binding webUrl}" VerticalAlignment="Top" Width="244"/>
<Button Content="Save" HorizontalAlignment="Left" Margin="267,166,0,0" VerticalAlignment="Top" Width="75" Command="{Binding SaveCommand}" />
<TextBox HorizontalAlignment="Left" Height="23" Margin="10,38,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<Label Content="{Binding errorMessage}" HorizontalAlignment="Left" Margin="10,167,0,0" VerticalAlignment="Top" RenderTransformOrigin="-5.611,10.822" Width="207" Height="19"/>
</Grid>
</Window>
BrowseViewModel
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;
using System.Threading;
using System.Threading.Tasks;
using System.Configuration;
using System.Collections.Specialized;
using System.IO;
namespace Data
{
public class BrowseViewModel : BaseViewModel
{
#region public variables
public string webUrl { get; set; }
public string errorMessage { get; set; }
#endregion
#region Public Commands
public ICommand SaveCommand { get; set; }
#endregion
#region Constructor
public BrowseViewModel()
{
this.SaveCommand = new RelayCommand(SaveFilePath);
}
#endregion
#region Private methods
private void SaveFilePath()
{
if (File.Exists(webUrl))
{
ConfigurationManager.AppSettings.Add("WebUrl", webUrl);
}
else
{
errorMessage = "Filen existerar ej";
}
}
#endregion
}
}
BrowseDialog.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.Shapes;
using System.IO;
using Data;
namespace TextalkApi
{
/// <summary>
/// Interaction logic for BrowseDialog.xaml
/// </summary>
public partial class BrowseDialog : Window
{
public BrowseDialog()
{
InitializeComponent();
this.DataContext = new BrowseViewModel();
}
}
}
BaseViewModel
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using PropertyChanged;
namespace Data
{
[AddINotifyPropertyChangedInterface]
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
}
}
Your XAML looks correct and I highly suspect it is the ViewModel causing it not to work. Something like this should work.
Please note that this will depend a lot on how the BaseViewModel has been implemented. If possible can you share this so I can update my answer to be correct? The below is how you should implement the properties in your ViewModel which is the DataContext of the View.
#region Properties
private string _webUrl;
public string WebUrl
{
get => _webUrl;
set
{
//This will change based on how you have implemented your BaseViewModel!
//The method name might be different, or have different parameters!
this.SetProperty(ref _webUrl, value, nameof(WebUrl));
//Call the save file path validation method...
SaveFilePath();
}
}
private string _errorMessage;
public string ErrorMessage
{
get => _errorMessage;
private set
{
//This will change based on how you have implemented your BaseViewModel!
//This method should call NotifyPropertyChange to notify the UI to update...
this.SetProperty(ref _errorMessage, value, nameof(ErrorMessage));
}
}
#endregion
In your ViewModelBase you can add a generic SetProperty method that can then handle raising the property changed event for you. Something like this:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void SetProperty<T>(ref T storage, T value, string propertyName)
{
storage = value;
RaisePropertyChangedEvent(propertyName);
}
protected void RaisePropertyChangedEvent(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
and because of the changes in the ViewModel you will also need to update the bindings in your XAML.
<Grid>
<Button Content="Browse" HorizontalAlignment="Left" Margin="267,11,0,0" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="FileDialog" HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" Text="{Binding WebUrl}" VerticalAlignment="Top" Width="244"/>
<Button Content="Save" HorizontalAlignment="Left" Margin="267,166,0,0" VerticalAlignment="Top" Width="75" Command="{Binding SaveCommand}" />
<TextBox HorizontalAlignment="Left" Height="23" Margin="10,38,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<Label Content="{Binding ErrorMessage}" HorizontalAlignment="Left" Margin="10,155,0,0" VerticalAlignment="Top" RenderTransformOrigin="-5.611,10.822" Width="207" Height="46"/>
</Grid>
Related
I get the error message which is written in the title.
My XAML looks like this:
<Window x:Class="LINQ3_Test_aus_LINQ2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:LINQ3_Test_aus_LINQ2"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<TextBox x:Name="txt_LiefNr" HorizontalAlignment="Left" Height="26" Margin="55,50,0,0" TextWrapping="Wrap" Text="{Binding LiefNr}" VerticalAlignment="Top" Width="125"/>
<TextBox x:Name="txt_LiefName" HorizontalAlignment="Left" Height="26" Margin="55,93,0,0" TextWrapping="Wrap" Text="{Binding LiefName}" VerticalAlignment="Top" Width="125"/>
<Button x:Name="btn_LiefNr" Content="Button" HorizontalAlignment="Left" Height="26" Margin="215,50,0,0" VerticalAlignment="Top" Width="116" Command="{Binding LookupCommand}"/>
</Grid>
and my MainViewModel.cs like this:
using GalaSoft.MvvmLight.Command;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace LINQ3_Test_aus_LINQ2
{
public class MainViewModel : INotifyPropertyChanged
{
private string _liefNr;
private string _liefName;
public ICommand LookupCommand { get; set; }
public string LiefNr
{
get { return _liefNr; }
set
{
_liefNr = value;
OnPropertyChanged();
}
}
public string LiefName
{
get { return _liefName; }
set
{
_liefName = value;
OnPropertyChanged();
}
}
public MainViewModel()
{
LookupCommand = new RelayCommand(Lookup);
}
private void Lookup()
{
Excel.OpenFile();
LiefName = Excel.Fill(LiefNr);
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I cant find a solution to this error thats why i am asking you. I have checked multiple times if something is wrong the the names, but there is not its all written correctly.
Hi I this two different modes to binding visibility from a parent's property .
for standar control is possible tom use this:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Window.Resources>
<Button x:Name="buttonTest" Width="75" Visibility="{Binding IsModify, Converter={StaticResource BoolToVis}}"/>
but to my usercontrol I only this way to binding the visibility , otherwise doesn't works:
<local:UserControl4 Height="100" Width="100" Visibility="{Binding ElementName=Window1,Path=IsModify,Converter={StaticResource BoolToVis}}"/>
My question is why I need to pass the element name plus ParentProperty at my control visibility , but for button no?
this is the codeBehind
public static readonly DependencyProperty IsModifyProperty =
DependencyProperty.Register("IsModify", typeof(Boolean), typeof(MainWindow), new PropertyMetadata(false));
[DefaultValue(false)]
public Boolean IsModify
{
get { return (Boolean)GetValue(MainWindow.IsModifyProperty); }
set
{
SetValue(MainWindow.IsModifyProperty, value);
this.OnPropertyChanged("IsModify");
}
}
and this is the constructor
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
here the source code to replicate the error.
you needs one project with one window and one usercontrol.
source code for window
---- XAML ----
<Window
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:local="clr-namespace:XTesting" x:Name="windowTest" x:Class="XTesting.WindowTest"
Title="WindowTest" Height="300" Width="583.908">
<Window.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<local:UserControl4
HorizontalAlignment="Left"
Height="65"
Margin="300,30,0,0"
VerticalAlignment="Top"
Width="230"
Visibility="{Binding IsModify, Converter={StaticResource BoolToVis}}"
Background="#FFF86161" Description="Custom Control"/>
<Button x:Name="buttonTest"
Content="Modify"
HorizontalAlignment="Left"
Margin="45,30,0,0"
VerticalAlignment="Top"
Width="225"
Visibility="{Binding IsModify, Converter={StaticResource BoolToVis}}"
Height="65"/>
<Button x:Name="button"
Content="Skisem (Click me)"
HorizontalAlignment="Left"
Height="75"
Margin="225,160,0,0"
VerticalAlignment="Top"
Width="135"
Click="button_Click_1"
Cursor="Hand"/>
</Grid>
this is the codebehind of window
using System;
using System.Collections.Generic;
using System.ComponentModel;
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 XTesting
{
/// <summary>
/// Interaction logic for WindowTest.xaml
/// </summary>
public partial class WindowTest : Window
{
public static readonly DependencyProperty IsModifyProperty =
DependencyProperty.Register("IsModify", typeof(Boolean), typeof(WindowTest), new PropertyMetadata(false));
[DefaultValue(false)]
public Boolean IsModify
{
get { return (Boolean)GetValue(WindowTest.IsModifyProperty); }
set
{
SetValue(WindowTest.IsModifyProperty, value);
this.OnPropertyChanged("IsModify");
}
}
public WindowTest()
{
InitializeComponent();
this.DataContext = this;
}
private void button_Click_1(object sender, RoutedEventArgs e)
{
IsModify = !IsModify;
}
#region - INotifyPropertyChanged implementation -
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion - INotifyPropertyChanged implementation -
}
}
this is the source code for usercontrol
XAML:
<UserControl x:Class="XTesting.UserControl4"
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="37" d:DesignWidth="310" MinWidth="7"
MouseLeftButtonUp="Selector1_MouseLeftButtonUp" FontSize="20">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="GridRoot">
<Grid.RowDefinitions>
<RowDefinition Height="37*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="51"/>
<ColumnDefinition Width="259*"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="TextBoxDescription"
Margin="0"
TextWrapping="Wrap"
Grid.Column="1"
Text="{Binding Description}"
Background="{x:Null}"
BorderBrush="{x:Null}"
Foreground="{Binding Foreground,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
FontSize="{Binding FontSize,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
VerticalContentAlignment="Center"
IsReadOnly="True"
SelectionBrush="{x:Null}"
BorderThickness="0"
Focusable="False"
IsTabStop="False"
IsUndoEnabled="False"
AllowDrop="False"
Padding="1,0,0,0"
MaxLines="1"
/>
</Grid>
and this is the code behind:
using System;
using System.Collections.Generic;
using System.ComponentModel;
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 XTesting
{
/// <summary>
/// Interaction logic for UserControl4.xaml
/// </summary>
public partial class UserControl4 : UserControl, INotifyPropertyChanged
{
#region - Delegate -
public delegate void ClickHandler(Object sender, RoutedEventArgs e);
#endregion - Delegate -
#region - Events -
public event ClickHandler Click;
#endregion - Events -
#region - Dependency Properties mandatory for Binding -
public static readonly DependencyProperty DescriptionProperty =
DependencyProperty.Register("Description", typeof(String), typeof(UserControl4), new PropertyMetadata(String.Empty));
#endregion - Dependency Properties for Binding -
#region - Properties -
/// <summary>
/// Gets or sets the description
/// </summary>
[Category("Common"), Description("gets or sets The description")]
public String Description
{
get { return (String)GetValue(UserControl4.DescriptionProperty); }
set
{
SetValue(UserControl4.DescriptionProperty, value);
this.OnPropertyChanged("Description");
}
}
#endregion - Properties -
public UserControl4()
{
InitializeComponent();
this.DataContext = this;
}
private void Selector1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (Click != null) Click(sender, e);
}
#region - INotifyPropertyChanged implementation -
// Basically, the UI thread subscribes to this event and update the binding if the received Property Name correspond to the Binding Path element
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion - INotifyPropertyChanged implementation -
}
}
I think the problem is in the constructor This.datacontext= this;
but this is mandatory if i want binding the property description.
Thanks in advance
You should probably add the user control DataContext on the GridRoot element instead of the UserControl4 class itself. The user control usage should be controlled mainly by the instantiating code and only its content should be controlled by the user control itself.
Also, I prefer to assign the data context on the Loaded event instead of the constructor, but this might just be my personal preference.
<UserControl x:Class="XTesting.UserControl4" Loaded="UserControl4_Loaded" ...
// ...
private void UserControl4_Loaded(object sender, RoutedEventArgs e)
{
GridRoot.DataContext = this;
}
I am working on WPF C#, MVVM Model. I have issue with Save_Button in View. All the things like getter, setter, RelayCommand initialization are working, just nothing happens when I click on 'Save' Buton. So it seems like Binding from View to ViewModel is not working. I am providing here only necessary files of View, ViewModel and Command part. Kindly help.
VehicalForm.xaml
<Window x:Class="Seris.VehicalForm"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<WrapPanel Orientation="Vertical" Margin="10 " >
<Label Content="Vehical No" HorizontalAlignment="Left"/>
<TextBox Name="VehicalNo_Text" Height="23" TextWrapping="Wrap" Text="TextBox" HorizontalAlignment="Left"/>
<Label Content="Model" HorizontalAlignment="Left"/>
<TextBox Name="Model_Text" Height="23" TextWrapping="Wrap" Text="TextBox" HorizontalAlignment="Left" />
<Label Content="Manufacturing Date" HorizontalAlignment="Left"/>
<DatePicker/>
<Label Content="IU No" HorizontalAlignment="Left"/>
<TextBox Height="23" Name="IUNO_Text" TextWrapping="Wrap" Text="TextBox" HorizontalAlignment="Left"/>
<Label Content="Personnel" HorizontalAlignment="Left"/>
<ComboBox Name="Personnel_Combo" HorizontalAlignment="Left" Width="116"/>
<Separator Height="20" RenderTransformOrigin="0.5,0.5" Width="16"/>
<Button Name="Save_Button" Command="{Binding SaveToList}" Content="Save" Width="66"/>
<ListView Height="294" Width="371" >
<ListView.View>
<GridView>
<GridViewColumn Header="lkj"/>
<GridViewColumn Header="lkj"/>
<GridViewColumn Header="lkj"/>
</GridView>
</ListView.View>
</ListView>
</WrapPanel>
VehicalForm.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 Seris
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class VehicalForm : Window
{
public VehicalForm()
{
InitializeComponent();
}
}
}
VehicalMainViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Seris.Models;
using System.Collections.ObjectModel;
using System.Windows.Input;
using Seris.Commands;
using Seris.ViewModels;
namespace Seris.ViewModels
{
public class VehicalMainViewModel : ObservableObject
{
ObservableCollection<VehicalModel> listItems = new ObservableCollection<VehicalModel>();
#region Getter-Setter
private string _VehicalNo;
public string VehicalNo
{
get { return _VehicalNo; }
set
{
if (value != _VehicalNo)
{
_VehicalNo = value.Trim();
OnPropertyChanged("ProductName");
}
}
}
private string _Model;
public string Model
{
get { return _Model; }
set
{
if (value != _Model)
{
_Model = value.Trim();
OnPropertyChanged("ProductName");
}
}
}
private DateTime _ManufacturingDate;
public DateTime ManufacturingDate
{
get { return _ManufacturingDate; }
set
{
if (value != _ManufacturingDate)
{
_ManufacturingDate = value;
OnPropertyChanged("ProductName");
}
}
}
private string _IUNo;
public string IUNo
{
get { return _IUNo; }
set
{
if (value != _IUNo)
{
_IUNo = value.Trim();
OnPropertyChanged("ProductName");
}
}
}
private string _PersonnelName;
public string PersonnelName
{
get { return _PersonnelName; }
set
{
if (value != _PersonnelName)
{
_PersonnelName = value.Trim();
OnPropertyChanged("ProductName");
}
}
}
#endregion
private ICommand _saveButton_Command;
public ICommand SaveButton_Command
{
get { return _saveButton_Command; }
set { _saveButton_Command = value; }
}
public void SaveToList(object o1)
{
listItems.Add(new VehicalModel(VehicalNo,Model,ManufacturingDate,IUNo,PersonnelName));
}
public void RemoveFromList()
{
}
public VehicalMainViewModel()
{
VehicalModel vm=new VehicalModel();
SaveButton_Command = new RelayCommand(new Action<object>(SaveToList));
}
}
}
RelayCommand.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
namespace Seris.Commands
{
public class RelayCommand : ICommand
{
private Action<object> _action;
public RelayCommand(Action<object> action)
{
_action = action;
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_action(parameter);
}
}
}
try in XAML
<Button Name="Save_Button" Command="{Binding SaveButton_Command}" … />
You tried to Bind to the Method instead of the Command.
<Button Name="Save_Button" Command="{Binding SaveButton_Command}" />
Have you set the DataContext in on your VehicalForm-Window?
public VehicalForm()
{
InitializeComponent();
this.DataContext = new VehicalMainViewModel();
}
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"));
}
}
}
}
}
I have a DLL with the following code
using System.Text;
using Microsoft.Win32;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ApplicationCheck
{
public class ApCkr
{
#region .NET
public string Netframeworkavailable()
{
bool NETinstall;
RegistryKey k1 = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Client");
if (k1 == null)
{
NETinstall = false;
}
else
{
NETinstall = true;
}
return NETinstall.ToString();
}
#endregion
#region PDF
public string PDFavailable()
{
bool PDFinstall;
RegistryKey k2 = Registry.ClassesRoot.OpenSubKey(".pdf");
if (k2 == null)
{
PDFinstall = false;
}
else
{
PDFinstall = true;
}
return PDFinstall.ToString();
}
#endregion
#region IExplore
public string IEavailable()
{
bool IEversion;
string k3 = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Internet Explorer").GetValue("Version").ToString();
string z = k3.Substring(0, 1);
int a = Int32.Parse(z);
if (a < 8)
{
IEversion = false;
}
else
{
IEversion = true;
}
return IEversion.ToString();
}
#endregion
#region IIS
public string IISavailable()
{
bool IISinstall;
RegistryKey k4 = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\InetStp");
if (k4 == null)
{
IISinstall = false;
}
else
{
IISinstall = true;
}
return IISinstall.ToString();
}
#endregion
}
}
And a WPF window with the followig XAML code
<Window x:Class="WpfApplication1.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ResizeMode="CanResizeWithGrip"
WindowStyle="None" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
Title="Window2" Height="350" Width="525">
<Grid>
<Label Content="Windows" Height="25" HorizontalAlignment="Left" Margin="12,15,0,0" Name="label1" VerticalAlignment="Top" Width="106" />
<Label Content="Edition " Height="25" HorizontalAlignment="Left" Margin="12,45,0,0" Name="label2" VerticalAlignment="Top" Width="106" />
<Label Content="Service Pack " Height="25" HorizontalAlignment="Left" Margin="12,75,0,0" Name="label3" VerticalAlignment="Top" Width="106" />
<Label Content="Version " Height="25" HorizontalAlignment="Left" Margin="12,105,0,0" Name="label4" VerticalAlignment="Top" Width="106" />
<Label Content="Processor Bits " Height="25" HorizontalAlignment="Left" Margin="12,135,0,0" Name="label5" VerticalAlignment="Top" Width="106" />
<Label Content="OS Bits " Height="25" HorizontalAlignment="Left" Margin="12,165,0,0" Name="label6" VerticalAlignment="Top" Width="106" />
<Label Content="Program Bits " Height="25" HorizontalAlignment="Left" Margin="12,195,0,0" Name="label7" VerticalAlignment="Top" Width="106" />
<TextBlock Height="21" HorizontalAlignment="Left" Margin="114,19,0,0" Name="textBlock1" Text="{Binding Path=var}" VerticalAlignment="Top" Width="249" ContextMenuOpening="textBlock1_ContextMenuOpening" />
</Grid>
</Window>
and the WPF's c# code
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.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Window2.xaml
/// </summary>
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
private void textBlock1_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
var NET = new ApplicationCheck.ApCkr();
textBlock1.Text = NET.Netframeworkavailable();
this.DataContext = textBlock1;
}
}
}
I researched data binding in MSDN and At stack overflow namely this - DataBinding Between a WPF GUI and a couple of ListBox/CheckBox
and others but i cannot get it right.And although stack overflow helped me utilise this in a console app.Now i have to do this in a WPF window.
Edit:I have to display the returned values from the DLL
In order to present the data from the DLL in the UI using binding, you need to have an object with public getters. In your UI DLL create a class (in mvvm design patern, this class is called 'View Model') with the public getters:
public class ApCkrVm {
public string netFrameworkAvailable {
get { return ApCkr.NetFrameworkAvailable(); }
}
public string pdfAvailable {
get { return ApCkr.PDFAvailable(); }
}
...
}
Then, in Window2 constructor, set ApCkrVm to be the DataContext:
public Window2( ) {
this.DataContext = new ApCkrVm( );
InitializeComponent( );
}
Finally, add text blocks in the XML file, binding the Text to the properties:
<TextBlock Text="{Binding Path=netFrameworkAvailable}" ... />
Some other comments:
You aren't utilizing very well the <Grid> element. You'll be better off defining ColumnDefinitions and RowDefinitions, creating a 2xn table.
ApCkr method can all be static. This class has no context.
I don't think your application could run if .net framework isn't available. If your application is running, you can safely put 'true' there.
Consider caching the values in ApCkrVm.
First add that Dll in your resources after that write following code in your wpf form xaml side.
<Window x:Class="TestWpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="220" Width="343"
xmlns:my="clr-namespace:TestWpfControlLibrary;assembly=TestWpfControlLibrary" Left="Auto" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" WindowStyle="None">
this following last line is impotent. it decide you use the particular dll.
xmlns:my="clr-namespace:TestWpfControlLibrary;assembly=TestWpfControlLibrary"`
after that in xaml page within grid teg use define "my", whome you use in xmlns:my
for that use following code.
<my:UserControl1 Height="168" HorizontalAlignment="Left" Margin="10,22,0,0" VerticalAlignment="Top" Width="307" Name="login" />
after that go to form.cs page and write the following code in pageload method
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
login.Visibility = System.Windows.Visibility.Visible;
}
}
now your dll is working properly.
you can download a test application like this from following link
http://www.dotnetfoundation.somee.com/Style/DesktopApp/WPF TEST.zip