I have a oxyplot charts. When the method "OnClearAll" is called I want these charts to disappear/ be deleted.
I want something like this:
private void OnClearAll()
{
HistoView.Clear();
}
However clear does not exist.
What should I write instead to delete my chart?
My MainPanel xaml:
<oxy:PlotView x:Name ="HistoView" Model="{Binding HistogramModel}" Margin="476,304,102,459"/>
My histogram class:
namespace myNameSpace
{
public class Histogram : INotifyPropertyChanged
{
//private Histogram DataContext;
public Collection<Item> Items { get; set; }
private PlotModel histogramModel;
public PlotModel HistogramModel //{ get; set; }
{
get { return histogramModel; }
set { histogramModel = value; OnPropertyChanged("HistogramModel"); }
}
public class Item
{
public string Label { get; set; }
public double Value { get; set; }
}
public event PropertyChangedEventHandler PropertyChanged;
//NotifyPropertyChangedInvocator
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public Histogram(List<double> frequency, List<double> axis, string VariableName)
{
CreateRectangleBar(frequency, axis, VariableName);
}
Try to set the Model or DataContext property to null:
private void OnClearAll()
{
HistoView.DataContext = null;
}
Related
I want to read some data from database and do some process on them and then view them in the view.
I read a lot about MVVM and now I am confused.
Imaging I read a person entity from database with Name attribute.
please make a small code and show me how should I make my model and ViewModel.
I guess it we will be something like this :
public class PersonModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string Name;
public string name
{
get
{
return Name;
}
set
{
Name = value;
onpropertychanged("name");
}
}
public PersonModel( string s)
{
name = s;
}
public void onpropertychanged(string PName)
{
if (PropertyChanged !=null)
{
PropertyChanged(this, new PropertyChangedEventArgs(PName));
}
}
}
public class PersonViewModel
{
public ObservableCollection <PersonModel> list { get; set; }
public PersonViewModel()
{
list = new ObservableCollection<model>();
list.Add(new model("abc"));
list.Add(new model("def"));
}
public void change()
{
list[1].name = "changed";
}
}
public class ViewModelBase
{
public PersonViewModel vperson { get; set; }
public ViewModelBase()
{
vperson = new PersonViewModel();
vperson.change();
}
}
Edite : Where should database connections be?
Edite :
<Grid>
<TextBox Text="{Binding vperson.list[1].name}" />
</Grid>
</Window>
I edited your classes and is working
public class PersonModel : INotifyPropertyChanged
{
private string _name;
public string Name
{
get => _name;
set
{
if (_name == value) return;
_name = value;
OnPropertyChanged();
}
}
public PersonModel(string name)
{
_name = name;
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class PersonViewModel
{
public ObservableCollection<PersonModel> Items { get; set; }
public PersonViewModel()
{
Items = new ObservableCollection<PersonModel> { new PersonModel("abc"), new PersonModel("def") };
}
public void Change()
{
Items[1].Name = "changed";
}
}
public class ViewModelBase
{
public PersonViewModel PersonViewModel { get; set; }
public ViewModelBase()
{
PersonViewModel = new PersonViewModel();
PersonViewModel.Change();
}
}
//Use the dataContext in this way, will help you with the strong type
xmlns:viewModels="clr-namespace:WpfApp1.ViewModels"
<Window.DataContext>
<viewModels:ViewModelBase />
</Window.DataContext>
<Grid>
<TextBox Text="{Binding PersonViewModel.Items[1].Name}" />
</Grid>
I have an observable collection which is the item source to a combo box. When I add a new item to the observable collection, it appears in the combobox. However, when I update an existing item, it does not update the combo box. What am I doing wrong?
xaml:
<ComboBox ItemsSource="{Binding ChildGroupOC}" DisplayMemberPath="childGroupName" />
observable collection property:
public ObservableCollection<ChildGroupBO> ChildGroupOC
{
get
{ return childGroupOC;}
set
{
childGroupOC = value;
}
}
public class ChildGroupBO: INotifyPropertyChanged
{
public int parentGroupId { get; set; }
public int childGroupId { get; set; }
public string childGroupName { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}
Your implementation of ChildGroupComboBoxBO not only has to implement INotifyPropertyChanged but also call the event on changes:
OnPropertyChanged("parentGroupId");
Example from MSDN:
public class Person : INotifyPropertyChanged
{
private string name;
// Declare the event
public event PropertyChangedEventHandler PropertyChanged;
public Person()
{
}
public Person(string value)
{
this.name = value;
}
public string PersonName
{
get { return name; }
set
{
name = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("PersonName");
}
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
I have simple gallery with notes and text box to add new one by title.
I use mvvm, other bindings work correcty.
When I set title of note and click add property NewNote.Title is updated and object saved in database. After that I clear NewNote.Title but UI is not updated.
here is short video https://youtu.be/l3vFwI-a4TQ
xaml
<TextBox Text="{Binding NewNote.Title}" />
page view model
class NotesPageViewModel : INotifyPropertyChanged
{
public ObservableCollection<NoteViewModel> Notes { get; set; }
public NoteViewModel NewNote { get; set; }
public NotesPageViewModel()
{
NewNote = new NoteViewModel();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
internal void LoadNotes()
{
using (var uow = new UnitOfWork())
{
Notes.Clear();
uow.NotesRepository.OrderBy(n => n.Position).ToList()
.ForEach(note => Notes.Add((NoteViewModel)note));
}
}
internal void AddNote()
{
if (string.IsNullOrWhiteSpace(NewNote.Title))
return;
using (var uow = new UnitOfWork())
{
uow.NotesRepository.Add((Note)NewNote);
uow.Complete();
}
NewNote.Title = "";
LoadNotes();
}
}
object view model
class NoteViewModel : INotifyPropertyChanged
{
public int Id { get; set; }
public string Title { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
You're not calling the OnPropertyChanged on the viewmodel when you're setting the property
class NoteViewModel : INotifyPropertyChanged
{
private int _id;
public int Id
{
get { return _id; }
set
{
_id = value;
OnPropertyChanged("Id");
}
}
private string _title;
public string Title
{
get { return _title; }
set
{
_title = value;
OnPropertyChanged("Title");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Also, the LoadNotes and AddNotes should be called via a command, and the new title should be sent as a parameter.
https://msdn.microsoft.com/en-us/library/ms752308(v=vs.110).aspx
I am trying to bind the data displayed in a DataGrid to a dynamic list of object (WhisperModel) which is inside another object(WhisperReader). The DataGrid only displays the headers, but no values. How can I make the DataGrid dynamically update itself when the list "whispers" is changed?
Main Window XAML:
<DataGrid x:Name="whisperDataGrid" Margin="10,69,10,10" IsReadOnly="True" ItemsSource="{Binding}"/>
Main Window C#
public partial class MainWindow : Window
{
private WhisperReader wr;
public MainWindow()
{
InitializeComponent();
wr = new WhisperReader();
whisperDataGrid.DataContext = wr.whispers;
}
WhisperReader:
class WhisperReader
{
public ObservableCollection<WhisperModel> whispers { get; private set; }
public WhisperReader()
{
whispers = new ObservableCollection<WhisperModel>();
}
WhisperModel:
class WhisperModel
{
public DateTime sentTime { get; set; }
public string sender { get; set; }
public string message { get; set; }
}
I think your problem is that it doesn't know when to update itself because:
You have made the whispers list the data context.
The properties that you are binding to don't use INotifyPropertyChanged.
WhisperReader and WhisperModel are not public
All bindings must be public, must be properties, and must call the PropertyChanged method.
The PropertyChanged function triggers the binding updates.
Try this...
public partial class MainWindow : Window
{
private WhisperReader wr;
public MainWindow()
{
InitializeComponent();
wr = new WhisperReader();
whisperDataGrid.DataContext = wr;
}
public class WhisperReader : INotifyPropertyChanged
{
ObservableCollection<WhisperModel> _whispers;
public ObservableCollection<WhisperModel> whispers
{
get { return _whispers; }
private set
{
_whispers = value;
NotifyPropertyChanged();
}
}
public WhisperReader()
{
whispers = new ObservableCollection<WhisperModel>();
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public class WhisperModel : INotifyPropertyChanged
{
public DateTime sentTime { get; set; }
private string _sender;
public string sender
{
get { return _sender; }
set { _sender = value; NotifyPropertyChanged();
}
private string _message;
public string message
{
get { return _message; }
set { _message = value; NotifyPropertyChanged();
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
<DataGrid x:Name="whisperDataGrid" Margin="10,69,10,10" IsReadOnly="True" AutoGenerateColumns="True" ItemsSource="{Binding whispers}"/>
I am using a ListBox in my Metro UI media player, but the ListBox doesn't show any text when I run it. I don't have any errors or so, but there is no text. I have also tried to use a ListView and not a ListBox, but the result was the same. What can I do ?
I am using the next code for the ListBox on the XAML part of the page
<ListBox x:Name="ItemListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding PathToFile}"
FontSize="24" Margin="5,0,0,0" TextWrapping="Wrap" />
<TextBlock Text="{Binding HasVideo}"
FontSize="16" Margin="15,0,0,0"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and the next code on the page C# code :
public static ListBox ListBoxIstance = null;
public MainPage()
{
InitializeComponent();
ListBoxIstance = ItemListBox;
ItemListBox.ItemsSource = Data_Repository.MediaData.MediaList;
ItemListBox.DataContext = Data_Repository.MediaData.MediaList;
}
where MediaList is a list declared as it follows
public static List<MediaFile> MediaList = new List<MediaFile>();
and MediaFile is a class
public class MediaFile
{
public TimeSpan Duration = TimeSpan.Zero;
public bool HasAudio = false;
public bool HasVideo = false;
public String PathToFile = null;
public MediaFile(string _pathToFile)
{
PathToFile = _pathToFile;
}
}
I am using the next code to update the MediaList and the ItemListBox
foreach (var pathToFile in files)
{
MediaList.Add(new MediaFile(pathToFile.Path));
MainPage.ListBoxIstance.UpdateLayout();
}
EDIT : After some suggestions :
That's how the MediaFile class looks like :
public class MediaFile : INotifyPropertyChanged
{
private bool _hasAudio;
public bool HasAudio
{
get { return _hasAudio; }
set
{
_hasAudio = value;
OnPropertyChanged("HasAudio");
}
}
private bool _hasVideo;
public bool HasVideo
{
get { return _hasVideo; }
set
{
_hasVideo = value;
OnPropertyChanged("HasVideo");
}
}
private String _pathToFile;
public String PathToFile
{
get { return _pathToFile; }
set
{
_pathToFile = value;
OnPropertyChanged("PathToFile");
}
}
public MediaFile(string pathToFile)
{
PathToFile = pathToFile;
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
and I am using
public static ObservableCollection<MediaFile> MediaList = new ObservableCollection<MediaFile>();
You can't bind to public fields in your item class. Turn the class members into public properties:
public class MediaFile
{
public TimeSpan Duration { get; set; }
public bool HasAudio { get; set; }
public bool HasVideo { get; set; }
public String PathToFile { get; set; }
public MediaFile(string _pathToFile)
{
PathToFile = _pathToFile;
}
}
Then use an ObservableCollection instead of a List. That would automatically update the ItemsSource binding when items are added or removed. No need to call UpdateLayout.
public ObservableCollection<MediaFile> MediaList =
new ObservableCollection<MediaFile>();
If you also want to update the UI when any of the property values changes after a MediaFile object has been added to the list, you also have to implement the INotifyPropertyChanged interface:
public class MediaFile : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private bool hasVideo
public bool HasVideo
{
get { return hasVideo; }
set
{
hasVideo = value;
OnPropertyChanged("HasVideo");
}
}
// other properties
}
You can only bind with properties and not with fields. Change fields to properties.
public bool HasVideo {get;set;}
public String PathToFile {get;set;}