C# WPF MVVM: Calling an Object - wpf

I have a QuestionsFile class, which has questions, a name etc...
Now I have created a wpf application and I have a window which has different pages. These pages inherit the BaseViewModel class. I create my pages in the WindowViewModel class (where I pass a new QuestionsFile object to the constructor and dispatch it through the constructors of the other viewmodels):
var chooseQFVM = new ChooseQuestionsFileViewModel(this.QuestionsFile);
var showChosenQFVM = new ShowChosenQuestionsFileViewModel(this.QuestionsFile);
var pages2 = new List<WizardControlViewBaseModel>();
pages2.Add(chooseQFVM);
pages2.Add(showChosenQFVM);
pages = new ReadOnlyCollection<WizardControlViewBaseModel>(pages2);`
All these viewmodels inherit the BaseViewModel class which has the QuestionsFile property.
so when let's say I change the QuestionsFile property of the chooseQFView variable from a combobox and I give it through - the same property in the BaseBiewModel class must be changed. So this is this code of the property in the BaseBiewModel class:
public QuestionsFile QuestionsFile
{
get { return qfile; }
set
{
qfile = value;
OnPropertyChanged("QuestionsFile");
}
}
So I call the PropertyChanged event, but when i want to call this property in the next page and I debug it says that all the properties of my QuestionsFile are null..
this is the code where I change the value of the QuestionsFile property:
public OptionViewModel<QuestionsFile> SelectedFile
{
get
{
return selectedFile;
}
set
{
selectedFile = value;
OnPropertyChanged("SelectedFile");
this.QuestionsFile = value.GetValue();
}
}

From what I understand on your view you have a collection of QuestionFiles (via OptionsViewModel) that you are selecting one of them via the SelectedFile property. At this point in time you are setting the chosen QuestionFile property.
This is all good for the ChooseQuestionViewModel (which I assume contains the SelectedFile property). I am not sure this is your issue but the SelectedFile will not reflect inside the ShowQuestionsFileViewModel because now both view models refer to a different instance.
Is this your issue? That you cannot see change of the selected QuestionFile in the ShowQuestionsFileViewModel?
If so you will need to tell the other view model that it has changed via events or having it reference the ChooseQuestionViewModel so it can listen for the PropertyChanged event so you can grab the selected item from and update itself.
i.e.
//Ctor
public ShowQuestionsFileViewModel(ChooseQuestionViewModel chooseViewModel)
{
_chooseViewModel = chooseViewModel;
chooseViewModel.PropertyChanged += ChoosePropertyChanged
}
private void ChoosePropertyChanged(object sender, PropertyChangedEventArgs e)
{
if(e.Property == "SelectedFile")
{
this.SelectedFile = _chooseViewModel.SelecteFile;
}
}

Related

How to send notification about the change of composite collection

I've got a composite collection. After modifications on its items from code behind I want the View to get updated. But I don't know how to notify the view. I tried the INotifyCollectionChanged, but it didn't work for me.
protected ObservableCollection<ScriptParameterComboItem> cItems
public virtual CompositeCollection CItems
{
get
{
return new CompositeCollection {new CollectionContainer {Collection = cItems}};
}
}
public void ConvertValue(params object[] parameters)
{
string newAverageOption = DisplayValueConverter.Convert(1, parameters);
var enumItem = cItems[1];
enumItem.Value = newAverageOption;
RaiseCollectionChanged("CItems");
}
protected void RaiseCollectionChanged(string property)
{
if(CollectionChanged != null)
CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
}
Your ScriptParameterComboItem class must implement INotifyPropertyChanged. So when changing it's properties, listeners will be notified. Using ObservableCollection helps listeners to be notified when something is added to the collection or removed from. Not changing the actual data within every single item.

Notifying my UI to refresh when a collection in it's VM changes

I have a usercontrol bound to a VM. This VM contains a collection property, lets call it "MyCollection" and several regular properties lets call one of them "SomeProperty". As you can see, the get and set logic for this property references the collection in the VM.
The problem is, when I make a change to "MyCollection", this obviously has an impact on the values that are shown in the UI (as they are calculated based on it). However, my UI doesn't appear to be smart enough to update itself whenever "MyCollection" changes.
Here is the VM my usercontrol is bound to:
public class MyVM
{
private ObservableCollection<SomeOtherVM> _myCollection = new ObservableCollection<SomeOtherVM>();
public MyVM()
{
}
public ObservableCollection<SomeOtherVM> MyCollection
{
get { return _myCollection; }
[Notify]
set
{
_myCollection = value;
}
}
public virtual string SomeProperty
{
get
{
if (_myCollection.Count == 1)
return _myCollection[0].SomeProperty;
else
return "More than one "SomeOtherVM" has been selected";
}
[Notify]
set
{
foreach (SomeOtherVM s in _myCollection)
{
s.SomeProperty = value;
}
}
}
}
}
Note that nothing in my usercontrol is directly bound to the collection, it is only bound to other properties that reference the collection in its get; set; methods.
Is there anything I could do in the VM to force the UI to update whenever "MyCollection" is changed? I want to avoid having to put anything in the code behind for the user control.
Subscribe to CollectionChanged of MyCollection and fire PropertyChanged-notifications for the other properties there (no fancy attribute usage for you).

How do I access different form's object for my windows form app

I have like 2 or 3 different forms and for example for my mainForm, I would like to access the object in settingsForm. How do I do that.
You need to expose that object, via a public property on settingsForm.
e.g.
In your settings form:
public Object MyObject
{
get { return myobject; }
}
then, on your main form, your can say;
settingsForm sf = new settingsForm();
sf.Show();
...
Console.Write(sf.MyObject.Text);
So. let's say settingsForm has a textbox that stores a value you want.
If you need access to the entire text box, you'd add a property on settings forms....
public TextBox textbox1
{
get { return textbox1; }
}
then, any form that instantiates and uses settingsForm, can use textbox1.
If you only want to access the value in textbox1, you'd only expose its Text property.
public string TextBoxValue
{
get { return textbox1.Text; }
}
public partial class mainForm : Form
{
settingForm settingObject;
public mainForm(settingForm settingObject)
{
InitializeComponent();
this.settingObject= settingObject;
}
}
the above code shows a simple way of how you access the object.

Binding Custom Object Datagrid Silverlight 4

I create an object Custom as you can see below
public class GridViewModel
{
private List _listRowCust = new List();
public List ListRowCust
{
get { return _listRowCust; }
set { _listRowCust = value; }
}
}
public class RowCustom
{
private List<CellCustom> _listCellCustom = new List<CellCustom>();
public List<CellCustom> ListCellCustom
{
get { return _listCellCustom; }
set { _listCellCustom = value; }
}
public RowCustom() { }
}
I try to bind the custom object on the datagrid object available in silverlight4.
I wish to bind any cell on the datagrid. One line should identify by a row object and each cell by a cellCustom.
I use this code
textColumn = new DataGridTextColumn();
textColumn.Header = "RemainingWork";
textColumn.Binding = new Binding("Cell[0]"); //it's a supposed syntax possibility in fact I have 3 rows with 10 cells
GridElements.Columns.Add(textColumn);
GridElements.ItemsSource = e.GridViewModel.ListRowCust;
I don't find any explanation on How to custom the binding.
Do you have any idea?
Thank you
best regards,
Alexandre
I think you can only bind to public properties.
So CellCustom must have a public property to bind to, if that's the object used for the itemsSource, or data context.

WPF: How Do I edit the column properties of a base/parent class in the child class through the property editor/XAML?

I have created a class called ProductionDataUserControlBase and it derives from class UserControl. This base class has no XAML. Its purpose is to act as a base class for a grid that I encapsulate inside the class so that it can be modified when the class is inherited later. Inside the constructor of the base class, I also create the columns and add them to the Grid's collection. I created a public property called Columns and all it does is returns (get) the Columns property collection of the grid.
I have created a child class that derives from ProductionDataUserControlBase and it does contain XAML. In the property editor of the inherited control my Columns collection exists. I can open the collection through the property editor and add new columns. However, the columns editor does not contain the columns that I added in the base even though I can visually see the columns on the canvas.
I'm assuming this is because the columns that I added in the base are not in the XAML of the child. If I add the columns through XAML of the child it creates duplicate columns because they were added in the base. How can I edit the property of the columns that were added in the base without using code-behind in the child?
public partial class ProductionDataUserControlBase : UserControl
{
private RadGridView _grdProdData;
private Boolean _InitCalled = false; //Boolean variable used to control whether init was previously called.
//This is because the loaded event may be fired multiple times depending
//on what type of control it's been placed into.
public ProductionDataUserControlBase()
{
InitializeComponent();
}
public Telerik.Windows.Controls.GridViewColumnCollection Columns
{
get
{
return _grdProdData.Columns;
}
}
protected virtual void InitializeComponent()
{
if (!_InitCalled)
{
InitializeGrid();
Columns = _grdProdData.Columns;
this.AddChild(_grdProdData);
_InitCalled = true;
}
}
private void InitializeGrid()
{
Telerik.Windows.Controls.GridViewColumn grdCol = null;
this._grdProdData = new RadGridView();
this._grdProdData.AutoGenerateColumns = false;
grdCol = new Telerik.Windows.Controls.GridViewColumn() { HeaderText = "PSTAT", Name = "grdColPSTAT", UniqueName = "PSTAT" };
_grdProdData.Columns.Add(grdCol);
grdCol = new Telerik.Windows.Controls.GridViewColumn() { HeaderText = "PCONO", Name = "grdColPCONO", UniqueName = "PCONO" };
_grdProdData.Columns.Add(grdCol);
}
}
<ProductionDataUserControlBase x:Class="AmerenProductionDataUserControl"
xmlns:MSControls="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="clr-namespace:AmerenProductionDataUserControl;assembly=AmerenProductionDataUserControl" xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation">
</ProductionDataUserControlBase>
public partial class AmerenProductionDataUserControl : ProductionDataUserControlBase
{
public AmerenProductionDataUserControl()
{
InitializeComponent();
}
}
Sounds like you either overrid the contents of the collection or overrode the property.

Resources