Changes in MainWindows.xaml.cs DropImages won't update LiveCharts, meaning that after initializing dropPhotos1 in public MainWindow(), changes from ChooseReference_OnClick(object sender, RoutedEventArgs e) won't affect plot despite the fact that values from scatterplot.xaml.cs get updated.
I have MainWindow.xaml.cs:
namespace DDrop
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ObservableCollection<DropPhoto> DropImages = new ObservableCollection<DropPhoto>();
public static readonly DependencyProperty dropPhotos1Property =
DependencyProperty.Register("dropPhotos1", typeof(ObservableCollection<DropPhoto>), typeof(MainWindow), new FrameworkPropertyMetadata(null));
ObservableCollection<DropPhoto> dropPhotos1
{
get { return (ObservableCollection<DropPhoto>)GetValue(dropPhotos1Property); }
set { SetValue(dropPhotos1Property, value); }
}
public MainWindow()
{
InitializeComponent();
Photos.ItemsSource = DropImages;
dropPhotos1 = DropImages;
}
private void ChooseReference_OnClick(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Jpeg files (*.jpg)|*.jpg|All files (*.*)|*.*";
openFileDialog.Multiselect = false;
openFileDialog.AddExtension = true;
if (openFileDialog.ShowDialog() == true)
{
Properties.Settings.Default.Reference = openFileDialog.FileName;
ReferenceImage.Source = new BitmapImage(new Uri(openFileDialog.FileName));
}
DropImages.Add(new DropPhoto
{
Drop = new Drop()
{
RadiusInMeters = 11
}
});
}
}
I imported plot user control into MainWindow.Xaml:
<uc:ScatterPlot VovaPhotos = "{Binding dropPhotos1, ElementName=myWindow}"/>
scatter plot xaml:
<UserControl x:Class="DDrop.Controls.ScatterPlot"
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"
xmlns:local="clr-namespace:DDrop.Controls"
xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance local:ScatterPlot}">
<Grid>
<lvc:CartesianChart Name="а" Series="{Binding SeriesCollection}" LegendLocation="Right" >
<lvc:CartesianChart.AxisY>
<lvc:Axis Title="Радиус, м" LabelFormatter="{Binding YFormatter}"></lvc:Axis>
</lvc:CartesianChart.AxisY>
<lvc:CartesianChart.AxisX>
<lvc:Axis Title="Время, с" Labels="{Binding Labels}"></lvc:Axis>
</lvc:CartesianChart.AxisX>
</lvc:CartesianChart>
</Grid>
</UserControl>
scatterplot.xaml.cs:
namespace DDrop.Controls
{
/// <summary>
/// Логика взаимодействия для UserControl1.xaml
/// </summary>
public partial class ScatterPlot : UserControl
{
public static readonly DependencyProperty VovaProperty =
DependencyProperty.Register("VovaPhotos", typeof(ObservableCollection<DropPhoto>), typeof(ScatterPlot));
public ObservableCollection<DropPhoto> VovaPhotos
{
get { return (ObservableCollection<DropPhoto>)GetValue(VovaProperty); }
set { SetValue(VovaProperty, value); }
}
public ScatterPlot()
{
InitializeComponent();
if (DesignerProperties.GetIsInDesignMode(this))
{
return;
}
Loaded += SudokuUniGrid_Loaded;
}
private void SudokuUniGrid_Loaded(object sender, RoutedEventArgs e)
{
ChartValues<double> values = new ChartValues<double>();
foreach (var dropPhoto in VovaPhotos)
{
values.Add(dropPhoto.Drop.RadiusInMeters);
}
SeriesCollection = new SeriesCollection
{
new LineSeries
{
Title = "Series 1",
Values = values,
LineSmoothness = 0, //0: straight lines, 1: really smooth lines
PointGeometry = Geometry.Parse("m 25 70.36218 20 -28 -20 22 -8 -6 z"),
PointGeometrySize = 50,
PointForeground = Brushes.Gray
},
};
Labels = new[] { "Jan", "Feb", "Mar", "Apr", "May" };
YFormatter = value => value.ToString("C");
а.Update();
DataContext = this;
}
public SeriesCollection SeriesCollection { get; set; }
public string[] Labels { get; set; }
public Func<double, string> YFormatter { get; set; }
}
}
DropPhoto model:
using System.ComponentModel;
namespace DDrop.BE.Models
{
public class DropPhoto : INotifyPropertyChanged
{
private Drop _drop;
public Drop Drop
{
get
{
return _drop;
}
set
{
_drop = value;
OnPropertyChanged(new PropertyChangedEventArgs("Drop"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChanged?.Invoke(this, e);
}
}
}
Drop model:
using System;
using System.ComponentModel;
namespace DDrop.BE.Models
{
public class Drop : INotifyPropertyChanged
{
private double _radiusInMeters;
public double RadiusInMeters
{
get
{
return _radiusInMeters;
}
set
{
_radiusInMeters = value;
OnPropertyChanged(new PropertyChangedEventArgs("RadiusInMeters"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChanged?.Invoke(this, e);
}
}
}
I managed to do update them, by implementing INotifyPropertyChanged
using DDrop.BE.Models;
using LiveCharts;
using LiveCharts.Wpf;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace DDrop.Controls
{
/// <summary>
/// Логика взаимодействия для UserControl1.xaml
/// </summary>
public partial class ScatterPlot : UserControl, INotifyPropertyChanged
{
public static readonly DependencyProperty VovaProperty =
DependencyProperty.Register("VovaPhotos", typeof(ObservableCollection<DropPhoto>), typeof(ScatterPlot));
public ObservableCollection<DropPhoto> VovaPhotos
{
get { return (ObservableCollection<DropPhoto>)GetValue(VovaProperty); }
set { SetValue(VovaProperty, value); OnPropertyChanged(new PropertyChangedEventArgs("VovaPhotos")); }
}
public ScatterPlot()
{
InitializeComponent();
if (DesignerProperties.GetIsInDesignMode(this))
{
return;
}
Loaded += SudokuUniGrid_Loaded;
}
private void SudokuUniGrid_Loaded(object sender, RoutedEventArgs e)
{
ChartValues<double> values = new ChartValues<double>();
foreach (var dropPhoto in VovaPhotos)
{
values.Add(dropPhoto.Drop.RadiusInMeters);
}
SeriesCollection = new SeriesCollection
{
new LineSeries
{
Title = "Series 1",
Values = values,
LineSmoothness = 0, //0: straight lines, 1: really smooth lines
PointGeometry = Geometry.Parse("m 25 70.36218 20 -28 -20 22 -8 -6 z"),
PointGeometrySize = 50,
PointForeground = Brushes.Gray
},
};
Labels = new[] { "Jan", "Feb", "Mar", "Apr", "May" };
YFormatter = value => value.ToString("C");
а.Update();
DataContext = this;
}
private SeriesCollection _series;
public SeriesCollection SeriesCollection
{
get
{
return _series;
}
set
{
_series = value;
OnPropertyChanged(new PropertyChangedEventArgs("SeriesCollection"));
}
}
public string[] Labels { get; set; }
public Func<double, string> YFormatter { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChanged?.Invoke(this, e);
}
}
}
Related
I have this tiny demo that appears to show that ListView continually creates ViewCells, and binds them to the one view model, until it runs out of memory. Here's the code...
From MainPage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="LVD.MainPage">
<StackLayout>
<Label Text="This is a listview with one item."/>
<Label Text="{Binding MainNum}"/>
<ListView x:Name="DemoList"
ItemsSource="{Binding Itms}"
RowHeight="75"
CachingStrategy="RecycleElement">
</ListView>
</StackLayout>
</ContentPage>
MainPage.xaml.cs:
public partial class MainPage : ContentPage
{
MainVM _vm = null;
public MainPage()
{
InitializeComponent();
_vm = new MainVM();
BindingContext = _vm;
DemoList.ItemTemplate = new DataTemplate(typeof(myCell));
}
}
MainVM.cs:
using System.Collections.ObjectModel;
namespace LVD
{
class MainVM
{
public string MainNum { get; set; }
private static int _mainserno = 0;
public ObservableCollection<CellVM> Itms { get; set; }
public MainVM()
{
MainNum = "Parent serial#: " + _mainserno.ToString();
_mainserno++;
if (Itms == null)
Itms = new ObservableCollection<CellVM>();
else
Itms.Clear();
CellVM item = new CellVM();
Itms.Add(item);
//CellVM item2 = new CellVM();
//Itms.Add(item2);
}
}
}
myCell.cs:
using Xamarin.Forms;
namespace LVD
{
class myCell : ViewCell
{
static int _localserialno = 0;
Label VMnumLbl, CellNumLbl, PLbl;
public static readonly BindableProperty ItemProperty =
BindableProperty.Create("CellItem", typeof(CellVM), typeof(myCell), null);
public CellVM CellItem
{
get { return (CellVM)GetValue(ItemProperty); }
set { SetValue(ItemProperty, value); }
}
public myCell()
{
VMnumLbl = new Label();
VMnumLbl.SetBinding(Label.TextProperty, "VMSerNum", BindingMode.Default, null, "VM Serial #: {0}");
CellNumLbl = new Label();
CellNumLbl.SetBinding(Label.TextProperty, "CellSerNum", BindingMode.Default, null, "Cell Serial #: {0}");
PLbl = new Label();
PLbl.SetBinding(Label.TextProperty, "PingCount", BindingMode.Default, null, "Pings: {0}");
var stackit = new StackLayout();
stackit.Children.Add(VMnumLbl);
stackit.Children.Add(CellNumLbl);
stackit.Children.Add(PLbl);
View = stackit;
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
if (BindingContext == null)
CellItem = null;
else if (BindingContext != CellItem)
{
CellItem = (CellVM)BindingContext;
CellItem.CellSerNum = _localserialno++;
CellItem.Ping();
}
}
}
}
CellVM.cs:
class CellVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private static int serialno = 0;
private int _vmserialno;
public int VMSerNum { get { return _vmserialno; } }
public int CellSerNum { get; set; }
public int PingCount { get; set; }
public CellVM()
{
_vmserialno = serialno++;
PingCount = 0;
}
public void Ping()
{
PingCount++;
OnPropertyChanged(string.Empty);
}
}
When I run this code, the display looks like this:
This is a listview with one item.
Parent serial #: 0
VM Serial #: 0
Cell Serial #: ++
Pings: ++
The bottom two numbers continually increase. That means the listview recreates the CellView, and binds them all to the same viewmodel. If I put two items in the list, both cells have running Cell Serial #'s and Pings.
Since I couldn't find anyone else complaining about this, I must be doing something wrong. Can anyone enlighten me to what that might be?
advTHANKSance (pun intended)
I'm trying to make a chart (UWP-c#) which changes dynamically when It's source data changes.
For example:
xaml file:
<StackPanel>
<Button Name="scatterButton" Content="click" Click="ScatterButton_Click" />
<Charting:Chart x:Name="test_chart">
<Charting:ScatterSeries IndependentValuePath="Name" DependentValuePath="Amount" />
</Charting:Chart>
</StackPanel>
c#:
public class SmartPhone
{
public string Name { get; set; }
public int Amount { get; set; }
public int Other { get; set; }
}
public sealed partial class MainPage : Page
{
List<SmartPhone> lstSource = new List<SmartPhone>
{
new SmartPhone() { Name = "IPhone", Amount = 40, Other = 1 },
new SmartPhone() { Name = "Android", Amount = 30, Other = 1 },
new SmartPhone() { Name = "UWP", Amount = 25, Other = 2 }
};
public MainPage()
{
this.InitializeComponent();
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
LoadChartContent();
}
private void LoadChartContent()
{
(test_chart.Series[0] as ScatterSeries).ItemsSource = lstSource;
}
private void ScatterButton_Click(object sender, RoutedEventArgs e)
{
lstSource[0].Amount = 10;
}
}
The idea is when I click the button "Amount" value change and I want to see it change in the chart.
I tried many packages but this is the only one that really worked for me in UWP. tha NuGet is "WinRTXamlToolkit.Controls.DataVisualization".
Please try to focus on "ScatterSeries" since this is the one I need.
Thanks.
At first you should use ObservableCollection instead of List to automatically notify when items get added or removed.
To notify about changes you have to implement INotifyPropertyChanged and raise PropertyChanged event.
xaml:
<Charting:Chart x:Name="test_chart">
<Charting:ScatterSeries ItemsSource="{x:Bind LstSource}" IndependentValuePath="Name" DependentValuePath="Amount" />
</Charting:Chart>
SmartPhone class example:
public class SmartPhone : INotifyPropertyChanged
{
private int _amount;
public string Name { get; set; }
public int Amount
{
get { return _amount; }
set
{
this._amount = value;
NotifyPropertyChanged();
}
}
public int Other { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
MainPage class:
public sealed partial class MainPage : Page
{
public ObservableCollection<SmartPhone> LstSource
{
get { return lstSource; }
}
private ObservableCollection<SmartPhone> lstSource = new ObservableCollection<SmartPhone>
{
new SmartPhone() {Name = "IPhone", Amount = 10, Other = 1},
new SmartPhone() {Name = "Android", Amount = 30, Other = 1},
new SmartPhone() {Name = "UWP", Amount = 25, Other = 2}
};
public MainPage()
{
this.InitializeComponent();
//LoadChartContent();
}
private void ScatterButton_Click(object sender, RoutedEventArgs e)
{
lstSource[0].Amount = 30;
//lstSource.Add(new SmartPhone{Amount = 10, Name = "asd", Other = 2});
}
}
I hope it's all you need.
I'm using the Xceed checkable combobox.
I need to set a few items as checked items:
<xctk:CheckComboBox x:Name="cbFileType" DisplayMemberPath="Name" SelectedMemberPath="IsChecked"></xctk:CheckComboBox>
C# code:
public partial class DataSelector : UserControl
{
public class BoolStringClass
{
public string Name { get; set; }
public bool IsChecked { get; set; }
}
public BackupDataSelector()
{
InitializeComponent();
cbFileType.Items.Add(new BoolStringClass { Name = ".jpg", IsChecked = true });
cbFileType.Items.Add(new BoolStringClass { Name = ".bmp", IsChecked = false });
}
}
But ".jpg" item is not checked:
How can I set ".jpg" as checked item?
You should add the items to be selected to the SelectedItems collection of the CheckComboBox:
cbFileType.Items.Add(new BoolStringClass { Name = ".jpg", IsChecked = true });
cbFileType.Items.Add(new BoolStringClass { Name = ".bmp", IsChecked = false });
foreach (var selectedItem in cbFileType.Items.OfType<BoolStringClass>().Where(x => x.IsChecked))
cbFileType.SelectedItems.Add(selectedItem);
The solution from user mm8 works, but that not the MVVM way...
From the docs:
https://xceed.com/wp-content/documentation/xceed-toolkit-plus-for-wpf/Xceed.Wpf.Toolkit~Xceed.Wpf.Toolkit.CheckComboBox.html
And
https://xceed.com/wp-content/documentation/xceed-toolkit-plus-for-wpf/Xceed.Wpf.Toolkit~Xceed.Wpf.Toolkit.Primitives.Selector~SelectedMemberPath.html
You'll need an ObservableCollection and a class holding the IsChecked and Item properties that fire the notifychanged event.
Below the working example: When you click the Set A and C button the items A and C will be checked as expected.
MainWindow.xaml.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
namespace WpfApp6
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ViewModel viewModel;
public MainWindow()
{
InitializeComponent();
viewModel = new ViewModel();
foreach (var item in new string[] { "A", "B", "C", "D"})
{
viewModel.CheckComboBoxItems.Add(new CheckComboBoxItems { IsChecked = false, Item = item});
}
DataContext = viewModel;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
foreach (var checkBoxToSet in viewModel.CheckComboBoxItems)
{
if (checkBoxToSet.Item.Equals("A") || checkBoxToSet.Item.Equals("C"))
{
checkBoxToSet.IsChecked = true;
}
}
}
}
public class ViewModel
{
public ObservableCollection<CheckComboBoxItems> CheckComboBoxItems { get; set; } = new ObservableCollection<CheckComboBoxItems>();
}
public class CheckComboBoxItems : INotifyPropertyChanged
{
private bool _isChecked;
private string _item;
public bool IsChecked
{
get
{
return _isChecked;
}
set
{
_isChecked = value;
NotifyPropertyChanged("IsChecked");
}
}
public string Item
{
get
{
return _item;
}
set
{
_item = value;
NotifyPropertyChanged("Item");
}
}
private void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
MainWindow.xaml
<Window x:Class="WpfApp6.MainWindow"
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:WpfApp6"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<xctk:CheckComboBox ItemsSource="{Binding CheckComboBoxItems}" DisplayMemberPath="Item" SelectedMemberPath="IsChecked" Height="50" Width="150"/>
<Button Content="Set A und C" Width="150" Height="50" Margin="20" Click="Button_Click"/>
</StackPanel>
</Window>
I have a ListBox contains checkboxes in DataTemplate and I have two buttons "Select All" and "UnSelect All".I want to make that checkboxes to check all and uncheck all with clicking select and unselect buttons and I want to implement INotifyPropertyChanged to class. How Can I do that things?
Thanks for your answers in advance..
XAML CODE
<StackPanel>
<ListBox Name="lstUserDefination"
ScrollViewer.VerticalScrollBarVisibility="Auto" SelectionMode="Multiple">
<ListBox.ItemTemplate>
<DataTemplate>
<ListBoxItem>
<CheckBox Name="chkUser" Content="{Binding AuthorityName}"/>
</ListBoxItem>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
C# CODE
public partial class UserDefinationEdit : Window
{
public ObservableCollection<Authority> authorityList { get; set; }
public UserDefinationEdit()
{
InitializeComponent();
CreateCheckBoxList();
lstUserDefination.ItemsSource = authorityList;
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
DragMove();
}
}
public void CreateCheckBoxList()
{
authorityList = new ObservableCollection<Authority>();
authorityList.Add(new Authority() {AuthorityValue = 0, AuthorityName = "0 - " });
authorityList.Add(new Authority() { AuthorityValue = 1, AuthorityName = "1 - " });
authorityList.Add(new Authority() { AuthorityValue = 2, AuthorityName = "2 - " });
authorityList.Add(new Authority() { AuthorityValue = 3, AuthorityName = "3 - " });
authorityList.Add(new Authority() { AuthorityValue = 4, AuthorityName = "4 - " });
authorityList.Add(new Authority() { AuthorityValue = 5, AuthorityName = "5 - " });
authorityList.Add(new Authority() { AuthorityValue = 6, AuthorityName = "6 - " });
this.DataContext = this;
}
private void btnUnselectall_Click(object sender, RoutedEventArgs e)
{
lstUserDefination.UnselectAll();
}
private void btnSelectAll_Click(object sender, RoutedEventArgs e)
{
lstUserDefination.SelectAll();
}
}
public class Authority
{
public string AuthorityName { get; set; }
public int AuthorityValue { get; set; }
public bool IsChecked { get; set; }
}
}
Add binding for IsChecked property in ListBoxItem template
<CheckBox Name="chkUser" Content="{Binding AuthorityName}" IsChecked="{Binding IsChecked}"/>
And change your button handlers to
private void btnUnselectall_Click(object sender, RoutedEventArgs e)
{
foreach (var a in authorityList)
{
a.IsChecked = false;
}
}
private void btnSelectAll_Click(object sender, RoutedEventArgs e)
{
foreach (var a in authorityList)
{
a.IsChecked = true;
}
}
Note that your Authority class should implement INotifyPropertyChanged to make this work.
public class Authority : INotifyPropertyChanged
{
private string authorityName;
private int authorityValue;
private bool isChecked;
public string AuthorityName
{
get { return authorityName; }
set
{
authorityName = value;
NotifyPropertyChanged();
}
}
public int AuthorityValue
{
get { return authorityValue; }
set
{
authorityValue = value;
NotifyPropertyChanged();
}
}
public bool IsChecked
{
get { return isChecked; }
set
{
isChecked = value;
NotifyPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Implement INotifyPropertyChanged:
public class Authority : INotifyPropertyChanged
{
private string _authorityName;
public string AuthorityName
{
get { return _authorityName; }
set { _authorityName = value; NotifyPropertyChanged(); }
}
private string _authorityValue;
public string AuthorityValue
{
get { return _authorityValue; }
set { _authorityValue = value; NotifyPropertyChanged(); }
}
private bool _isChecked;
public bool IsChecked
{
get { return _isChecked; }
set { _isChecked = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Set the IsChecked property of all Authority objects:
private void btnUnselectall_Click(object sender, RoutedEventArgs e)
{
Select(false);
}
private void btnSelectAll_Click(object sender, RoutedEventArgs e)
{
Select(true);
}
private void Select(bool select)
{
foreach (Authority authority in authorityList)
authority.IsChecked = select;
}
Bind the IsChecked property in your XAML:
<CheckBox Name="chkUser" IsChecked="{Binding IsChecked}" Content="{Binding AuthorityName}"/>
I'm new to WPF and I can't get my grid to auto-refresh when some property changes.
Only thing I achieved - auto-refresh on element adding.
Here is my code:
public partial class MainWindow : Window
{
private Model model;
public MainWindow()
{
InitializeComponent();
model = new Model();
MyGrid.ItemsSource = model.Content;
}
private void MyButton_Click(object sender, RoutedEventArgs e)
{
MyGrid.Items.Refresh();
}
}
public class Model
{
public ObservableCollection<Single> Content;
private Random r;
private Action action;
private static object _syncLock = new object();
public Model()
{
Content = new ObservableCollection<Single>();
r = new Random();
action = new Action(process);
action.BeginInvoke(null,null);
BindingOperations.EnableCollectionSynchronization(Content, _syncLock);
}
private void process()
{
while (true)
{
Content.Add(new Single { Name = "name" });
Content[r.Next(0,Content.Count())].Name = "rename" + r.Next(1,100);
Thread.Sleep(1000);
}
}
}
public class Single : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
RaisePropertyChanged(Name);
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Make you model variable notifyable and this will work for you.
Try Changing the above code with.
public partial class Window1 : Window, INotifyPropertyChanged
{
private Model model;
public Model ModelData
{
get { return model; }
set
{
model = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("ModelData"));
}
}
public Window1()
{
this.InitializeComponent();
ModelData = new Model();
MyGrid.ItemsSource = ModelData.Content;
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class Model
{
public ObservableCollection<Single> Content { get; set; }
private Random r;
private static object _syncLock = new object();
public Model()
{
Content = new ObservableCollection<Single>();
Content.Add(new Single { Name = "name" });
r = new Random();
// BindingOperations.EnableCollectionSynchronization(Content, _syncLock);
DispatcherTimer t = new DispatcherTimer();
t.Interval = new TimeSpan(2000);
t.Tick += new EventHandler(t_Tick);
t.Start();
}
void t_Tick(object sender, EventArgs e)
{
App.Current.Dispatcher.BeginInvoke(new Action(() =>
{
if (Content.Count <= 100)
Content.Add(new Single { Name = "name" });
Content[r.Next(0, Content.Count())].Name = "rename" + r.Next(1, 100);
}));
}
}
public class Single : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
RaisePropertyChanged("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Xaml
<DataGrid Name="MyGrid" AutoGenerateColumns="False" Margin="246,175,0,0">
<DataGrid.Columns>
<DataGridTextColumn Header="Names" Binding="{Binding Name }" />
</DataGrid.Columns>
</DataGrid>
The problem was here:
public string Name
{
get { return name; }
set
{
name = value;
RaisePropertyChanged(Name);
}
}
Had to use
RaisePropertyChanged("Name");
Simple and stupid..