i have a few checkboxes an I want funcionality to check or uncheck all checkbox. Here is a class .cs and xaml code. How to add funcionality for check or uncheck all?
public static event PropertyChangedEventHandler IsCheckedChanged;
private bool isChecked;
public WorkStep(string name)
{
Name = name;
IsChecked = true;
}
public WorkStep(string name, bool isChecked)
{
Name = name;
IsChecked = isChecked;
}
public string Name
{
get;
}
public bool IsChecked
{
get { return isChecked; }
set
{
isChecked = value;
OnIsCheckedChanged();
}
}
private void OnIsCheckedChanged()
{
PropertyChangedEventHandler handler = IsCheckedChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs("IsChecked"));
}
and xaml:
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
I would use the INotifyPropertyChanged interface like shown in the class below:
public class myClass : INotifyPropertyChanged
{
private bool _IsChecked;
public bool IsChecked
{
get { return _IsChecked; }
set
{
_IsChecked = value;
OnPropertyChanged("IsChecked");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
Then I would bind the property IsChecked to all of my checkboxes like shown below in the xaml:
<Grid>
<CheckBox x:Name="checkBox1" IsChecked="{Binding IsChecked,UpdateSourceTrigger=PropertyChanged}" Content="CheckBox" HorizontalAlignment="Left" Margin="116,90,0,0" VerticalAlignment="Top"/>
<CheckBox x:Name="checkBox2" IsChecked="{Binding IsChecked,UpdateSourceTrigger=PropertyChanged}" Content="CheckBox" HorizontalAlignment="Left" Margin="116,126,0,0" VerticalAlignment="Top"/>
<CheckBox x:Name="checkBox3" IsChecked="{Binding IsChecked,UpdateSourceTrigger=PropertyChanged}" Content="CheckBox" HorizontalAlignment="Left" Margin="116,164,0,0" VerticalAlignment="Top"/>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="380,235,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>
In the MainWindow class make a new instance of the class where the IsChecked property is located (in my case myClass MyClass = new myClass()). Then add the newly created instance MyClass to the DataContext of your MainWindow (DataContext = MyClass;). I use a button control in this example to check and uncheck all of my checkboxes. If the value of the property IsChecked is true all of the checkboxes are checked and if it's false all of the checkboxes are unchecked. The MainWindow class is shown below :
public MainWindow()
{
InitializeComponent();
DataContext = MyClass;
}
myClass MyClass = new myClass();
private void button_Click(object sender, RoutedEventArgs e)
{
if(MyClass.IsChecked)
MyClass.IsChecked = false;
else
MyClass.IsChecked = true;
}
Related
I have a model, which contains CanDrawProperty. I want to bind this property to IsEnabled property of DataGrid CheckBox:
public class Series : INotifyPropertyChanged
{
private ObservableCollection<DropPhoto> _dropPhotosSeries;
public ObservableCollection<DropPhoto> DropPhotosSeries
{
get
{
return _dropPhotosSeries;
}
set
{
_dropPhotosSeries = value;
OnPropertyChanged(new PropertyChangedEventArgs("DropPhotosSeries"));
}
}
private bool _canDrawPlot;
public bool CanDrawPlot
{
get
{
if (_dropPhotosSeries?.Where(x => x.Drop.RadiusInMeters != null).ToList().Count > 1)
{
_canDrawPlot = true;
return _canDrawPlot;
}
_canDrawPlot = false;
return _canDrawPlot;
}
set
{
_canDrawPlot = value;
OnPropertyChanged(new PropertyChangedEventArgs("CanDrawPlot"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChanged?.Invoke(this, e);
}
}
I want to update my Datagrid CheckBox IsEnabled state based on CanDrawPlot property of this model. But this doesn't seem to work. XAML for DataGrid:
<DataGrid IsReadOnly="True" AutoGenerateColumns="False" SelectionMode="Single" Margin="0" BorderThickness="0" ClipToBounds="True" ItemsSource="{Binding User.UserSeries}" SelectionChanged="SeriesDataGrid_OnSelectionChanged" Name="SeriesDataGrid">
<DataGrid.Columns>
<DataGridTemplateColumn CanUserResize="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsEnabled="{Binding CanDrawPlot}" Checked="ChooseSeries_Checked" x:Name="ChooseSeries" Height="25"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
I have class User. It contains UserSeries. UserSeries has property CanDrawPlot:
public class User : INotifyPropertyChanged
{
private ObservableCollection<Series> _userSeries;
public ObservableCollection<Series> UserSeries
{
get
{
return _userSeries;
}
set
{
_userSeries = value;
OnPropertyChanged(new PropertyChangedEventArgs("UserSeries"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChanged?.Invoke(this, e);
}
}
You need to add the following lines to your code
In the xaml:
You need to add to bindinig the UpdateSourceTrigger
<CheckBox IsEnabled="{Binding CanDrawPlot,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Checked="ChooseSeries_Checked" x:Name="ChooseSeries" Height="25"/>
And in the xaml.cs you need to creat an instance of Series class
For example:
private Series series = new Series ();
And in the constructor of the xaml.cs you need to write:
DataContext = series;
Successfully.
I tried to bind a property to a nested object, but it fails.
I have taken a look at those questions, but i think i made another mistake somewhere else. Maybe someone can give i hind.
WPF: How to bind to a nested property?
binding to a property of an object
To upper slider/textbox has a correct binding while the lower one fails to do so.
I have two sliders with corrosponding textboxes:
<StackPanel>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox Text="{Binding Path= boundnumber, Mode=TwoWay, FallbackValue='binding failed'}" ></TextBox>
<Slider Value="{Binding Path= boundnumber, Mode=TwoWay}" Width="500" Maximum="1000" ></Slider>
</StackPanel>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding Path=myDatarow}">
<TextBox Text="{Binding Path= boundnumber, Mode=TwoWay, FallbackValue='binding failed'}" ></TextBox>
<Slider Value="{Binding Path= boundnumber, Mode=TwoWay}" Width="500" Maximum="1000" ></Slider>
</StackPanel>
</StackPanel>
Code behind:
public partial class MainWindow : INotifyPropertyChanged
{
public MainWindow()
{
DataContext = this;
InitializeComponent();
}
private int _boundnumber;
public int boundnumber
{
get { return _boundnumber; }
set
{
if (value != _boundnumber)
{
_boundnumber = value;
OnPropertyChanged();
}
}
}
Datarow myDatarow = new Datarow(11);
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyname = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
}
}
class Datarow : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyname = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
}
public Datarow()
{
}
public Datarow(int number)
{
boundnumber = number;
}
private int _boundnumber;
public int boundnumber
{
get { return _boundnumber; }
set
{
if (value != _boundnumber)
{
_boundnumber = value;
OnPropertyChanged();
}
}
}
}
You need to expose your myDatarow into a public property like your boundnumber.
private DataRow _myDatarow = new DataRow(11);
public DataRow myDataRow
{
get { return _myDatarow; }
}
And just an additional advice.
It's better to separate your DataContext class from the MainWindow.
I know I should use the MVVM pattern but I'm trying to get step by step closer to it. So here is my Listbox:
<ListBox x:Name="BoardList" ItemsSource="{Binding notes}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<TextBox IsReadOnly="True" ScrollViewer.VerticalScrollBarVisibility="Visible" Text="{Binding text}" TextWrapping="Wrap" Foreground="DarkBlue"></TextBox>
<AppBarButton Visibility="{Binding visibility}" Icon="Globe" Click="OpenInBrowser" x:Name="Link"></AppBarButton>
<AppBarButton Icon="Copy" Click="Copy"></AppBarButton>
<AppBarButton Icon="Delete" Click="Delete"></AppBarButton>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In the Mainpage.xaml.cs I declare the following:
ObservableCollection<BoardNote> notes = new ObservableCollection<BoardNote>();
So if I understood this right I don't need to care about the "INotifyCollectionChanged" stuff because I'm using an observablecollection?
So I got for example a textbox like this:
<Textbox x:Name="UserInputNote" Placeholdertext="Type in a text for your note"></Textbox>
And a button to Add the new note to the ObservableCollection and the click event is just like this:
notes.Add(new BoardNote(UserInputNote.Text));
So now the UI should update every time the user clicks the button to save a new note. But nothing happens. What did I do wrong?
If you need it here is the BoardNote class:
class BoardNote
{
public string text
{
get; set;
}
public BoardNote(string text)
{
this.text = text;
}
public Visibility visibility
{
get
{
if (text.StartsWith("http"))
return Visibility.Visible;
else
return Visibility.Collapsed;
}
}
}
You need to implement INotifyPropertyChanged. Here's one way of doing it.
Create this NotificationObject class.
public class NotificationObject : INotifyPropertyChanged
{
protected void RaisePropertyChanged<T>(Expression<Func<T>> action)
{
var propertyName = GetPropertyName(action);
RaisePropertyChanged(propertyName);
}
private static string GetPropertyName<T>(Expression<Func<T>> action)
{
var expression = (MemberExpression)action.Body;
var propertyName = expression.Member.Name;
return propertyName;
}
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Then your BoardNote class will inherit it this way:
class BoardNote : NotificationObject
{
private string _text
public string Text
{
get {return _text;}
set
{
if(_text == value) return;
_text = value;
RaisePropertyChanged(() => Text);
}
}
public BoardNote(string text)
{
this.text = text;
}
public Visibility visibility
{
get
{
if (text.StartsWith("http"))
return Visibility.Visible;
else
return Visibility.Collapsed;
}
}
}
I have a ListBox created by ItemTemplate and Binding
<controls:PanoramaItem Header="{Binding AppResources.SettingsSubpage2, Source={StaticResource LocalizedStrings}}" HeaderTemplate="{StaticResource HeaderTemplate}">
<Grid>
<ListBox x:Name="DayOfWeekSelector" ItemTemplate="{StaticResource DayOfWeekTemplate}" ItemsSource="{Binding DayOfWeekElementList}" Foreground="{StaticResource AppForegroundColor}" LostFocus="DayOfWeekSelector_LostFocus" HorizontalAlignment="Left" Width="420" />
</Grid>
</controls:PanoramaItem>
Template code:
<phone:PhoneApplicationPage.Resources>
<!--- ... --->
<DataTemplate x:Key="DayOfWeekTemplate">
<Grid Height="65" Width="332">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<CheckBox IsChecked="{Binding IsActive, Mode=TwoWay}" Tag="{Binding}" d:LayoutOverrides="Width, Height" BorderBrush="{StaticResource AppBackgroundColor}" Background="{StaticResource ScheduleBackgroundAccentsColor}" Grid.Column="0" Unchecked="CheckBox_Unchecked" />
<StackPanel Grid.Column="1" Orientation="Horizontal">
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" d:LayoutOverrides="Width"/>
<TextBlock Text="{Binding TaskCounter, Mode=OneWay, Converter={StaticResource DayOfWeekCounter}}" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="10,0,0,0"/>
</StackPanel>
</Grid>
</DataTemplate>
<!--- ... --->
And it's working fine. I've got all my items on the list. Checkboxes are binded to appropriate elements (clicking on it is changing proper value).
But by default ListBox can be also selected. Selection high-light TextBox binded to Name but don't change CheckBox (binded to IsActive). How can I tie item selection changing to checkbox state changing (in Silverlight)?
Edit:
public partial class SettingsPage : PhoneApplicationPage, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public List<DayOfWeekElement> DayOfWeekList
{
get
{
return CyberSyncPlanBase.Instance.DayOfWeekElementList;
}
set
{
CyberSyncPlanBase.Instance.DayOfWeekElementList = value;
NotifyPropertyChanged("DayOfWeekList");
}
}
public SettingsPage()
{
InitializeComponent();
DayOfWeekSelector.DataContext = CyberSyncPlanBase.Instance;
}
private void DayOfWeekSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DayOfWeekElement dowe = (DayOfWeekElement) DayOfWeekSelector.SelectedItem;
if (dowe != null)
dowe.IsActive = (dowe.IsActive) ? false : true;
}
And in singleton INotifyPropertyChanged i've implemented in the same way:
private List<DayOfWeekElement> dayOfWeekElementList;
public List<DayOfWeekElement> DayOfWeekElementList
{
get { return dayOfWeekElementList; }
set
{
dayOfWeekElementList = value;
RecalcWeekTasks();
NotifyPropertyChanged("DayOfWeekElementList");
}
}
Bottom class:
public class DayOfWeekElement
{
public string Name { get { return this.DayOfWeek.ToStringValue(); } }
public bool IsNotEmpty { get { return (TaskCounter > 0); } }
public int TaskCounter { get; set; }
public bool IsActive { get; set; }
public DayOfWeek DayOfWeek { get; set; }
}
I think you could use the SelectedItem property of the ListBox control.
A possible implementation could be this:
Subscribe to the event SelectedIndexChanged of the ListBox.
Get the selected item.
For the selected item, change its IsActive property to true.
This works if the interface INotifyPropertyChanged is implemented in your data class.
E.g.:
public class DayOfWeekElement : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private bool isActive = false;
public bool IsActive {
get
{
return this.isActive;
}
set
{
if (value != this.isActive)
{
this.isActive= value;
NotifyPropertyChanged("IsActive");
}
}
}
}
Hello I am new to WPF and I am not sure how to do the data binding and the code behind to get my textbox and button to be enabled and disabled.
If you could show me how to get it to work in the example below it would help me out in my project.
XAML
<ComboBox Name="ComboBoxA"
Margin="5"
SelectedIndex="0" SelectionChanged="ComboBoxA_SelectionChanged" >
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" Height="Auto" Margin="5" />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
<ComboBoxItem Content="Option1" Width="72" />
<ComboBoxItem Content="Option2" Width="72" />
<ComboBoxItem Content="Option3" Width="72" />
</ComboBox>
<TextBox Name="TextBoxA"
Margin="5"
Width="200"
IsEnabled="{Binding TextBoxEnabled}" />
<Button Name="ButtonA"
Content="Next"
HorizontalAlignment="left"
Margin="5"
IsEnabled="{Binding ButtonEnabled} />
C#
private void ComboBoxA_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
TextBoxA = new TextBox();
ButtonA = new Button();
if (ComboBoxAfterProcessing.SelectedIndex == 0)
{
TextBoxA.IsEnabled = false;
ButtonA.IsEnabled = false;
}
else if (ComboBoxAfterProcessing.SelectedIndex == 1)
{
TextBoxA.IsEnabled = true;
ButtonA.IsEnabled = true;
}
else if (ComboBoxAfterProcessing.SelectedIndex == 2)
{
TextBoxA.IsEnabled = true;
ButtonA.IsEnabled = true;
}
}
Write a class as follows which shall look like below
public class ViewMole:INotifyPropertyChanged
{
public ViewMole()
{
ListValues = new List<string>() { "Option1", "Option2", "Option3", "Option4",
"Option5" };
}
public ICommand Click
{
get
{
return new RelayCommand();
}
}
public List<string> ListValues
{
get;
set;
}
string a;
public string A
{
get
{
return a;
}
set
{
a = value;
RaisePropertyChanged("A");
}
}
int index=0;
public int SelectedIndex
{
get
{
return index;
}
set
{
index = value;
RaisePropertyChanged("SelectedIndex");
A = ListValues[index];
if (index == 0)
{
IsEnabled = false;
}
else
{
IsEnabled = true;
}
}
}
bool isEnabled;
public bool IsEnabled
{
get
{
return isEnabled;
}
set
{
isEnabled = value;
RaisePropertyChanged("IsEnabled");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Write another class which implements ICommand as below. This is to handel button click events
public class RelayCommand : ICommand
{
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
MessageBox.Show("Button cliked");
}
}
Change your Xaml below
<ComboBox Name="ComboBoxA" SelectedIndex="{Binding SelectedIndex, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding ListValues}"/>
<TextBox Name="TextBoxA" Margin="5" Width="200" Text="{Binding A}" IsEnabled="{Binding IsEnabled}"/>
<Button Name="ButtonA" Content="Next" HorizontalAlignment="left" Margin="5" Command="{Binding Click}" IsEnabled="{Binding IsEnabled}"/>
In Xmal.cs set the data Context as beolw
public MainWindow()
{
InitializeComponent();
DataContext = new ViewMole();
}
Refer the below links to understand why INotifyPropertyChanged and ICommand has to be used
http://wpftutorial.net/INotifyPropertyChanged.html
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
http://msdn.microsoft.com/en-us/library/system.windows.input.icommand.aspx
you can binding your textbox and button's IsEnabe Property to the Combox's SelectedIndex
Property and you neednot response to ComboBoxA_SelectionChanged Event. in order to let the
SelectedIndex change your button and textBox's IsEnabe you need a convetor in your binding
for example: