How to subsequently update the radio button - c#

I'm looping throught my database items and I'm displaying styled radio buttons and here's my code:
public ObservableCollection<Product> products = new ObservableCollection<Product>(ProductsController.SelectAllProducts());
if (products.Count > 0)
{
foreach(var item in products)
{
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush = (SolidColorBrush)(new BrushConverter().ConvertFrom("#004a80"));
RadioButton a = new RadioButton();
a.BorderThickness = new Thickness(1);
a.Background = Brushes.Green;
a.Foreground = new SolidColorBrush(Colors.Black);
a.BorderBrush = mySolidColorBrush;
a.Width = 118;
a.Height = 70;
a.Margin = new Thickness(5,0,0,5);
Style style = Application.Current.Resources["MyRadioButtonAsButtonStyle"] as Style;
a.Style = style;
a.ApplyTemplate();
a.Content = item.OrdinalNumber;
Image imgControl = (Image)a.Template.FindName("img", a);
Image imgControlWhite = (Image)a.Template.FindName("whiteImg", a);
TextBlock text = (TextBlock)a.Template.FindName("text", a);
a.Click += (object sender, RoutedEventArgs e) =>
{
var radioButton = sender as RadioButton;
MessageBox.Show(radioButton.Content.ToString());
};
text.Text = item.Title;
imgControl.Source = image;
spProducts.Children.Add(a);
}
}
On the beggining of my class I get all products from Db and I've created as many radio buttons as there are products and it looks like this:
If products.Count is 8 than we will see 8 radio buttons which are styled as buttons:
After while I would like to change background colour or title on the radio button but I would not like to refresh a whole screen so I've added INotifyPropertyChanged and product is list of type Product which looks like this:
public class Product : INotifyPropertyChanged
{
#region Attributes
private string _ordinalNumber;
private string _title;
private string _description;
#endregion
#region Properties
public string OrdinalNumber
{
get { return _ordinalNumber; }
set { _ordinalNumber = value; NotifyPropertyChanged("OrdinalNumber"); }
}
public string Title
{
get { return _title; }
set { _title = value; NotifyPropertyChanged("Title"); }
}
public string Description
{
get { return _description; }
set { _description = value; NotifyPropertyChanged("Description"); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
And somewhere in my code in same file I've tried to modify a title:
var dbProduct = ProductController.Instance.GetProductByTitle(title);
var listItem = products.FirstOrDefault(x => x.OrdinalNumber == dbProduct.OrdinalNumber);
listItem.Title = "Test";
But nothing happened, I thought since products was source for creating radio buttons, so if I change Title of some item in that list it would affect radio button on screen since I'm using that Title prop while I'm displaying radio button text.
Any kind of help would be awesome.

You need to create a binding for changes to be tracked in the UI. Something like this:
Instead of -
text.Text = item.Title;
Have this -
Binding binding = new Binding("Title");
binding.Source = item;
BindingOperations.SetBinding(text, TextBlock.TextProperty, binding);

Related

Update BackColor for ListBox

I need to update BackColor of my ListBox by selecting the color from combobox and when clicked on the button.Here is my code
public Data _current;
public Data Current
{
get
{ return _current; }
set
{
_current = value;
if (PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("Current"));
}
}
}
public Form1()
{
InitializeComponent();
Items = new ObservableCollection<Data>();
for (int i = 0; i < names.Count; i++)
{
Items.Add(new Data() {Name=names[i].ToString().TrimStart(new char[] { '[', 'C', 'o', 'l', 'o', 'r', ' ', ']' }).TrimEnd(new char[] { ']' }), color = names[i] });
}
comboBox1.DataSource = Items;
comboBox1.DisplayMember ="Name";
Current = Items.First();
}
public List<Color> names = new List<Color>() { Color.Red,Color.Yellow,Color.Green,Color.Blue };
public event PropertyChangedEventHandler PropertyChanged;
private void button1_Click(object sender, EventArgs e)
{
Current = comboBox1.SelectedItem as Data;
listBox1.DataBindings.Add("BackColor", Current, "color", true, DataSourceUpdateMode.OnPropertyChanged);
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
public class Data:INotifyPropertyChanged
{
private Color _color;
public string name { get; set; }
public string Name
{
get
{ return name; }
set
{
name = value;
if (PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
public Color color
{
get
{
return _color;
}
set
{
_color = value;
if (PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("color"));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Exception pop's out and says:"This causes two bindings in the collection to bind to the same property."
For solving your original problem "I need to update BackColor of my ListBox by selecting the color from combobox and when clicked on the button" you do not need databinding at all. You can just do it with
private void button1_Click( object sender, EventArgs e )
{
listBox1.BackColor = (Color)comboBox1.SelectedValue;
}
If you really want to do it with databinding, you can bind directly between listbox and combobox (ok, this does not involve a button click):
listBox1.DataBindings.Add( "BackColor", comboBox1, "SelectedValue", true, DataSourceUpdateMode.OnPropertyChanged );
If you need databinding and buttonclick you can bind combobox with form.Current
comboBox1.DataBindings.Add( "SelectedItem", this, "Current", true, DataSourceUpdateMode.OnPropertyChanged );
and update backcolor on button click:
private void button1_Click( object sender, EventArgs e )
{
listBox1.BackColor = Current.Color;
}
Here is the complete example incuding some more improvements:
public class Data : INotifyPropertyChanged
{
public string Name
{
get { return color.Name; }
}
private Color color;
public Color Color
{
get { return color; }
set
{
color = value;
if( PropertyChanged != null )
this.PropertyChanged( this, new PropertyChangedEventArgs( "Color" ) );
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class Form1 : Form
{
private ComboBox comboBox1;
private ListBox listBox1;
private Button button1;
public Form1()
{
InitializeComponent();
List<Data> dataList = new List<Data>
{
new Data { Color = Color.Red },
new Data { Color = Color.Yellow },
new Data { Color = Color.Green },
new Data { Color = Color.Blue },
};
comboBox1.DataSource = dataList;
comboBox1.DisplayMember = "Name";
comboBox1.ValueMember = "Color";
}
public Data Current
{
get { return comboBox1.SelectedItem as Data; }
}
private void button1_Click( object sender, EventArgs e )
{
listBox1.BackColor = Current.Color;
}
private void InitializeComponent()
{
//...
}
}
You can bind any property of a control only once, otherwise you will receive an ArgumentException:
This causes two bindings in the collection to bind to the same
property. Parameter name: binding
In your code you have added data-binding in click event handler of button and each time you click the code executes.
To solve the problem, move data-binding code to Load event of form.
If for any reason you want to add binding in click event of button, to solve the problem you can check if the binding has not been added then add the binding:
if (listBox1.DataBindings["BackColor"] == null)
listBox1.DataBindings.Add("BackColor", Current, "color", true,
DataSourceUpdateMode.OnPropertyChanged);

How To Update WPFToolkit AreaSeries Chart On Button Click

I am making WPFToolkit based Graph where i am trying to update AreaSeries every time i click on a button.
I have implemented INotifyPropertyChanged on my data class. but when i reload the data in the source object id doesn't updates in chart(target object)
the code is as below:
public partial class MainWindow : Window
{
static List<Ready4LOS> Ready4LOS = new List<Data.Ready4LOS>();
public MainWindow()
{
InitializeComponent();
chart1.DataContext = Ready4LOS;
InitChart();
LoadData();
}
private void LoadData()
{
var path = #"zxzxzxz.log";
Ready4LOS.Clear();
List<APISTATDataModel> daa = APISTATDataModel.GetFromFile(path, new string[] { "|" }, "Ready4TOS");
List<APISTATDataModel> lastn = daa.GetRange(daa.Count - 10, 10);
foreach (APISTATDataModel d in lastn)
{
Ready4LOS.Add(new Ready4LOS() { Case = d.Current_Count, Time = d.Current_Time });
}
}
private void InitChart()
{
System.Windows.Data.Binding indi = new System.Windows.Data.Binding("Case");
System.Windows.Data.Binding dep = new System.Windows.Data.Binding("Time");
dep.Mode = System.Windows.Data.BindingMode.OneWay;
indi.Mode = System.Windows.Data.BindingMode.OneWay;
AreaSeries ares = new AreaSeries();
ares.ItemsSource = Ready4LOS;
ares.IndependentValueBinding = dep;
ares.DependentValueBinding = indi;
ares.Title = "Ready4LOS";
DateTimeAxis dta = new DateTimeAxis();
dta.Interval = 10;
dta.IntervalType = DateTimeIntervalType.Minutes;
dta.Title = "Time";
dta.Orientation = AxisOrientation.X;
// dta.Minimum = DateTime.Now.AddMinutes(-90);
// dta.Maximum = DateTime.Now;
LinearAxis yaxis = new LinearAxis();
yaxis.Minimum = 0;
yaxis.Interval = 2;
yaxis.Title = "Case";
yaxis.Orientation = AxisOrientation.Y;
yaxis.ShowGridLines = true;
chart1.Axes.Add(yaxis);
chart1.Axes.Add(dta);
chart1.Series.Add(ares);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
LoadData();
chart1.UpdateLayout();
}
}
}
the data model is here
class Ready4LOS : INotifyPropertyChanged
{
int _case;
DateTime _time;
public int Case
{
get
{
return _case;
}
set
{
_case = value;
NotifyPropertyChanged("Case");
}
}
public DateTime Time
{
get
{
return _time;
}
set
{
_time = value;
NotifyPropertyChanged("Time");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
It loads perfectly when it starts as i've called the LoadData() in the beginning.
The problem is when i click on the refresh button it loads the data in the source object but the target object's data in not updated i.e. chart is not updated it remains the same as of initial data.
Use ObservableCollection<Ready4LOS>, not List<Ready4LOS>. ObservableCollection<> already implements INotifyPropertyChanged and also INotifyCollectionChanged. Your implementation of INotifyPropertyChanged for Ready4LOS may only be necessary if you're going to dynamically change values for Case and Time for existing Ready4LOS already in your collection.

Binding Textblock with datacontext code behing

I want to bind a border generated dynamically from code behind.
below is my model that I bind with the border.
public class MapTextboxGridModel : INotifyPropertyChanged
{
private MaptextBoxGridStylePropertiesModel _GridStyleProperties = new MaptextBoxGridStylePropertiesModel();
public MaptextBoxGridStylePropertiesModel GridStyleProperties
{
get { return _GridStyleProperties; }
set
{
_GridStyleProperties = value;
OnPropertyChanged("GridStyleProperties");
}
}
}
My style for each cells is in the _GridStyleProperties. And in _GridStyleProperties model I have one property "_Name" as below.
public class MaptextBoxGridStylePropertiesModel : INotifyPropertyChanged
{
private string _Name = "Enter your text";
public string Name
{
get { return _Name; }
set
{
_Name = value;
OnPropertyChanged("Name");
}
}}
// following border(multiple, so I will have border in each cell of the grid) is created inside a grid
MapTextboxGridModel cellcontext = new MapTextboxGridModel();
Border db = new Border();
db.MouseLeftButtonDown += db_MouseLeftButtonDown;
db.DataContext = cellcontext;
TextBlock block = new TextBlock() { Text = cellcontext.GridStyleProperties.Name };
and then when I click on any of the cell in the grid.
void db_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (columnpossition == -1 && rowpossition == -1)
{
columnpossition = Grid.GetColumn(sender as Border);
rowpossition = Grid.GetRow(sender as Border);
}
else
{
Border bod = sender as Border;
Grid grd = bod.Parent as Grid;
int col = Grid.GetColumn(bod);
int row = Grid.GetRow(bod);
if (col == columnpossition && row == rowpossition)
{
}
else
{
TextBlock dbtxt = bod.Child as TextBlock;
imodel.GridStyleProperties.needtoshow = true;
Binding textbnd = new Binding();
textbnd.Source = bod.DataContext as MapTextboxGridModel;
textbnd.Path = new PropertyPath("StyleProperties.Name"); // Is this possible
BindingOperations.SetBinding(dbtxt, TextBlock.TextProperty, textbnd);
columnpossition = col;
rowpossition = row;
}
}
}
I can't understand where am I making mistake. Please suggest me what change should be done in above code.

Xamarin.Forms simple binding to Label TextProperty

I am new to Xamarin.Forms and the binding concept. Can someone please tell me why this is not working? The name of the object itself is changing when I'm pressing the button. Why wont the Text-property update?
var red = new Label
{
Text = todoItem.Name,
BackgroundColor = Color.Red,
Font = Font.SystemFontOfSize (20)
};
red.SetBinding (Label.TextProperty, "Name");
Button button = new Button
{
Text = String.Format("Tap for name change!")
};
button.Clicked += (sender, args) =>
{
_todoItem.Name = "Namie " + new Random().NextDouble();
};
The todoItem is an object of the class below. The notification itself works, I am almost positive. I guess there's something wrong with my binding, or I am missing something with this concept.
public class TodoItem : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
string _name;
public string Name
{
get { return _name; }
set
{
if (value.Equals(_name, StringComparison.Ordinal))
{
// Nothing to do - the value hasn't changed;
return;
}
_name = value;
OnPropertyChanged();
}
}
void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
You need to set the Label's BindingContext:
red.BindingContext = _todoItem;

Xamarin.Forms DataBinding in code for Switch Cell

I have the following object:
public class Notification : INotifyPropertyChanged
{
private bool _trafficNot;
public bool TrafficNot
{
get { return _trafficNot; }
set {
if (value.Equals(_trafficNot))
return;
_trafficNot = value;
OnPropertyChanged();
}
}
private bool _newsNot;
public bool NewsNot
{
get { return _newsNot; }
set
{
if (value.Equals(_newsNot))
return;
_newsNot = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName]String propertyName=null)
{
var handler=PropertyChanged;
if(handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I get the data from an a object like this:
//set up the notification object according to what is stored in the DB
Notification notification = new Notification
{
TrafficNot = uInfo.NotificationTraffic,
NewsNot = uInfo.NotificationNews
};
and I want to bind the data to these switchells
TableView tableView = new TableView
{
BindingContext = notification,
Intent = TableIntent.Form,
Root = new TableRoot
{
new TableSection
{
new SwitchCell
{
Text = "News",
BindingContext = "NewsNot"
},
new SwitchCell
{
Text = "Traffic",
BindingContext = "TrafficNot"
},
new SwitchCell
}
}
};
What else do i need to do to bind it?
Cheers
You didn't bind view properties at all. Instead of assigning text to BindingContxt and Text property you should bind those Text properties, i.e.:
var sc = new SwitchCell();
sc.SetBinding(SwitchCell.TextProperty, new Binding("NewsNot"));
BindingContext is the source object while you are binding against its properties. See also DataBinding docs.

Categories

Resources