Encapsulating ListBox in public property - c#

In a MVP applicaiton if I want to encapsulate a ListBox in a public property so that I could expose the property through an interface to the presenter. I should be able to update the items in the ListBox though this public property. I've tried in several ways to do this
public BindingSource Permission
{
get { return lstGivenPermissions.DataSource; } // Casting error
set { lstGivenPermissions.DataSource = value; }
}
I tried several types for the property like IEnumereble<>, List<> etc. but always either setter or geter shows a casting error.
One option is to have separate properties for get and set.
public ListBox gettingPermission
{
get {return lstGivenPermissions; }
}
public BindingSource Permission
{
set { lstGivenPermissions.DataSource = value; }
}
Is it possible to use a single property in this case or else having two properties is a acceptable solution?
EDIT : I'm using MVP pattern and my requirement is that my presenters are talking to the Views through interfaces. So that if I want one of my presenters to access controllers (like text boxes) in the View, those controllers should be encapsulated in properties. So that I can expose through the interface.

This solved my problem.
public List<string> GivenPermission
{
get { return lstGivenPermissions.Items.Cast<string>().ToList(); }
set { lstGivenPermissions.DataSource = value; }
}

Related

Make updating a property in one class trigger the setter for a property of that type in another class

I am using MVVM with Galasoft MVVMLight libraries.
I have two models; each has a boolean property and different properties of the same type.
public class Model1 : ObservableObject
{
public EnumPair<YesNoInherit> Model1Property
{
get { return _model1Property; }
set
{
_model1Property = value;
Updated = true
RaisePropertyChanged("Model1Property");
}
}
public bool Updated
{
get { return _updated; }
set
{
_updated = value;
RaisePropertyChanged("Updated");
}
}
}
public class Model2 : ObservableObject
{
public EnumPair<YesNoInherit> Model2Property
{
get { return _model2Property; }
set
{
_model2Property = value;
Updated = true
RaisePropertyChanged("Model2Property");
}
}
public bool Updated
{
get { return _updated; }
set
{
_updated = value;
RaisePropertyChanged("Updated");
}
}
}
The type YesNoInherit is an enum having values No, Yes, and Inherit.
Here is the EnumPair class.
public class EnumPair<T> : ObservableObject where T : struct, IConvertible
{
public T EnumValue
{
get { return _enumValue; }
set
{
if (Type.Equals(value, _enumValue) == false)
{
_enumValue = value;
RaisePropertyChanged();
}
}
}
public string SourceName
{
get { return _sourceName; }
set
{
_sourceName = value;
RaisePropertyChanged();
}
}
}
In my view, I am trying to use a ComboBox to let the user select one of the three enum values, and, in some cases, display custom text. The resource "enumComboBoxTemplate" allows the ComboBox drop-down to show enum descriptions. The converter "inheritanceEnum2Desc" is where the custom text would be applied. "object1" is an instance of "Model1".
<ComboBox ItemTemplate=ItemTemplate="{StaticResource enumComboBoxTemplate}"
EnumSource="enums:YesNoInherit">
<ComboBox.Text>
<MultiBinding Converter="{StaticResource inheritanceEnum2Desc}">
<Binding Path="object1.EnumValue"/>
<Binding Path="object1.SourceName"/>
</MultiBinding>
</ComboBox.Text>
</ComboBox>
"Model2" would be used in future programming employing similar functionality, but with different data.
When I change the selection in the ComboBox, I want to change the value of "Updated" (from false to true) so I can enable a button in the view. This appears to require that the EnumPair class somehow make the program execute the setter for Model1Property. Since the two model classes have properties of type EnumPair, I don't believe I can add any code in EnumPair specific to either model class.
How can I accomplish this? I would greatly appreciate any assistance.
Basically, you have two options: either use some kind of message-bus to update the other model (Prism has EventAggregator, not sure about MVVMLight) or make both model instances forward their properties to a common data source that notifies all of its users when a property changes.
If you want to be able to easily change from one class to another in the future without rewriting all of your code, you need to create an Interface that defines all of the things that the two models have in common, and both model classes need to implement the interface. You could call the interface IModel1
So, instead of having a "Model1" in your viewmodel, you would have an "IModel1" in your viewmodel instead. You could pass in the same object you are passing in now, which is of type Model1, because it implements the IModel1 interface. When you are ready to switch, pass in a Model2 instead, and it will work without having to rewrite anything in your view or viewmodel. Your setters can be completely different - as long as both models have all of the methods and properties that are required by the interface, you will be OK.
Alternately, if Model2 is exactly like Model1 except that it has "extra stuff," you can make Model2 a derived class which derives from Model1.
Google searching either of those terms should point you toward a good tutorial.

ViewModel properties with multiple calls to PropertyChanged

Recently I've been learning C# and WPF for work. I'm trying to use MVVM on a project I'm working on, just to keep the code organized and learn how it works.
In MVVM, controls on the View bind to properties on the ViewModel, which implements INotifyPropertyChanged. Pretty often, when a certain property is updated, I'll want a bunch of other properties to get updated as a result.
For example, I have a ListBox with a TextBox above it. You can type in the TextBox, and it filters the stuff in the ListBox. But I also need to be able to clear the TextBox from code in certain cases. The code ends up looking like this:
private Collection<string> _listOfStuff;
public Collection<string> FilteredList
{
get
{
if (String.IsNullOrWhiteSpace(SearchText))
{
return _listOfStuff;
}
else
{
return new Collection<string>(_listOfStuff.Where(x => x.Contains(SearchText)));
}
}
set
{
if (value != _listOfStuff)
{
_listOfStuff = value;
OnPropertyChanged("FilteredList");
}
}
}
private string _searchText;
public string SearchText
{
get { return _searchText; }
set
{
if (value != _searchText)
{
_searchText = value;
OnPropertyChanged("SearchText"); // Tells the view to change the value of the TextBox
OnPropertyChanged("FilteredList"); // Tells the view to update the filtered list
}
}
}
As this project gets bigger, this is starting to feel sloppy. I have one setter with 6 calls to OnPropertyChanged and it's getting hard to keep track of stuff. Is there a better way to do this?
I tried out Assisticant on a project about a year ago. It figures out which of your properties need to raise notifications and also which are related. There is a good course for it on Pluralsight and the examples on the website are pretty good. If nothing else you could check out the source code to see how he did it.
Also some good suggestions from Change Notification in MVVM Hierarchies.
They mentioned:
Use an attribute -> e.g. [DependsUpon(nameof(Size))]
and
Josh Smith's PropertyObserver
Could put the raise property change calls in a method if you just need to raise the same notifications every time.
First you shouldn't do potentially expensive operations in a command, then you'll be able to remove the OnPropertyChanged("FilteredList"); from your SearchText.
So you should move that code from the getter and into it's own command and bind it from XAML (either as Command on a button or using Blends Interactivity Trigger to call it when the text fields value changes).
public ICommand SearchCommand { get; protected set; }
// Constructor
public MyViewModel()
{
// DelegateCommand.FromAsyncHandler is from Prism Framework, but you can use
// whatever your MVVM framework offers for async commands
SearchCommand = DelegateCommand.FromAsyncHandler(DoSearch);
}
public async Task DoSearch()
{
var result = await _listOfStuff.Where(x => x.Contains(SearchText)).ToListAsync();
FilteredList = new Collection<string>(result);
}
private Collection<string> _listOfStuff;
private Collection<string> _filteredList;
public Collection<string> FilteredList
{
get
{
return _filteredList;
}
set
{
if (value != _filteredList)
{
_filteredList = value;
OnPropertyChanged("FilteredList");
}
}
}
private string _searchText;
public string SearchText
{
get
{
return _searchText;
}
set
{
if (value != _searchText)
{
_searchText = value;
OnPropertyChanged("SearchText");
}
}
}
On a side note: You can also use OnPropertyChanged(nameof(FilteredList)); to have a refactor friendly version, when you rename your property all of your OnPropertyChanged calls will be updated to. Requires C# 6.0 though, but it's compatible with older .NET Frameworks (back to 2.0), but requires Visual Studio 2015 or later
For anyone searching for a good solution to this type of problem: Check out ReactiveUI.
It is a framework based on Reactive Extensions (Rx), with the idea that you model this type of dependencies between properties explicitly, without a jungle of RaisePropertyChanged(..).
Specifically check out the ObservableAsPropertyHelper (sometimes called OAPH).
You should only raise OnPropertyChanged in the setter of the property itself.
A cleaner implementation of your ViewModel can be:
private Collection<string> _listOfStuff;
private Collection<string> _filteredList;
public Collection<string> FilteredList
{
get
{
return _filteredList;
}
set
{
if (value != _filteredList)
{
_filteredList = value;
OnPropertyChanged("FilteredList");
}
}
}
private string _searchText;
public string SearchText
{
get { return _searchText; }
set
{
if (value != _searchText)
{
_searchText = value;
OnPropertyChanged("SearchText");
FilteredList = new Collection<string>(_listOfStuff.Where(x => x.Contains(SearchText)));
}
}
}
if you just don't wanna type only other option is to fire OnPropertyChanged for all properties which can be done by passing a null or string.Empty, although it will be sloppier code!
OnPropertyChanged(Null);
or
OnPropertyChanged(String.Empty);

C# - Default value of class

class StyleProperty<T>
{
static readonly StyleProperty<Object> INHERIT ;
T value;
public T Value
{
get { return this.value; }
set { this.value = value; }
}
}
Hello..
The above class sometimes should have the value INHERIT when value should not be used.. As
c# doesnt allow overloading Properties i cant set Value=StyleProperty.Inherit. i must be of type T.
Any idea what to do there?
After reading your comments, what about this:
class StyleProperty<T>
{
T _Value;
public StyleProperty(T inheritedValue)
{
_Value = inheritedValue;
}
public T Value
{
get { return this._Value; }
set { this._Value = value; }
}
}
Your first problem is how should the inherited value flow into the concrete instance? The only way i can think of would be the constructor. If the user doesn't like this value he can simply change it (to maybe the same value).
If you would use for inheritance some kind of global variable (but that wouldn't be inheritance, that would be a default value) you could also think about using a boolean flag which will be checked in the getter to find out if the backing store or the default should be used and it will set always to the opposite of its initial state within the setter.
class StyleProperty<T>
{
T _Value;
bool _UseBackingStore;
public T Value
{
get { return _UseBackingStore ? this._Value : INHERIT; }
set { this._Value = value; _UseBackingStore = true; }
}
}
Update
To get a skin support into your application i think you need to take a different approach. All forms and gui controls you are using should implement some kind of interface (e.g. ISkin). Also your application should have some kind of SkinSelector. This one holds all informations about coloring, fonts, etc and it also gets a reference to the MainForm. Within the constructor it recursively runs through the Controls property of the form and checks if there are any controls implementing your interface (simply using as ISkin and check for null). If it is skinnable, simply set the colors, fonts, etc. of the control as defined within you SkinSelector. Sounds quite easy but the problem is, that you have to derive all gui controls and add your interface to them. So this is not such a complicated thing, but maybe a lot of work. Maybe you can test if Generics can help you out by using a SkinWrapper<T> where T : Control and an extension function like ISkin ToSkinnableControl(this Control control)). But this will only work if you need to change a few common properties, that are the same for all controls. If you need more skin control e.g. for the DataGridView or a ComboBox i think derivement is the only way to help you out.
Not exactly sure what you're asking for, but you can define a default value for a property like this:
[DefaultValue(<Value>)]
public T Value
{
get { return this.value; }
set { this.value = value; }
}

WinForm DataBinding Hide Property in business object C# .NET

My datagrid (DevExpress) automatically will populate a grid based on the public fields of a business object.
What attribute can I place on the field to tell WinForm databinders to ignore it?
[???HideFromDataBindingSources???]
public bool IsSecurity
{
get { return _isSecurity; }
set { _isSecurity = value; }
}
You should decorate your property with Browsable(false)
Or even implement ICustomTypeDescriptor in your class and filter or dynamically add properties in more agile way.

WinForms data binding - Bind to objects in a list

I need some help/guidance on WinForms data binding and I can't seem to get Google to help me with this one.
Here is my scenario. Consider the following classes which is similar to what I need:
public class Car
{
public string Name { get; set; }
public List<Tire> Tires { get; set; }
}
public class Tire
{
public double Pressure { get; set; }
}
My instances of this will be an object of class Car with a List with four Tire objects. Note that I will always have a known number of objects in the list here.
Now I want to data bind this to a Form containing five textboxes. One textbox with the name of the car and one textbox with each of the tires pressures.
Any idea on how to make this work? The designer in VS does not seem to allow me to set this up by assigning to list indexes like Tires[0].Pressure.
My current solution is to bind to a "BindableCar" which would be like:
public class BindableCar
{
private Car _car;
public BindableCar(Car car)
{
_car = car;
}
public string Name
{
get { return _car.Name; }
set { _car.Name = value; }
}
public double Tire1Pressure
{
get { return _car.Tires[0].Pressure; }
set { _car.Tires[0].Pressure = value; }
}
public double Tire2Pressure
{
get { return _car.Tires[1].Pressure; }
set { _car.Tires[1].Pressure = value; }
}
public double Tire3Pressure
{
get { return _car.Tires[2].Pressure; }
set { _car.Tires[2].Pressure = value; }
}
public double Tire4Pressure
{
get { return _car.Tires[3].Pressure; }
set { _car.Tires[3].Pressure = value; }
}
}
but this becomes really ugly when my lists contains 20 instead of 4 objects, and for each of those objects I want to bind against 6 properties. That makes a huge "BindableObject"!
You should note that you can bind controls to any object type that implements the interfaces IList, ICollection or IEnumerable or inherits from classes that implement these interfaces. Generic collections also qualify for this kind of binding.
These are internally converted to an IBindingList instance.
Check out the following links for more information:
Roadmap for Windowsforms databinding - Takes a very comprehensive look at the implementation and possibilities and provides a variety of links to other KB articles.
Winforms Object binding - Rockford Lhotka's article on the subject. Provides a Windows forms designer-oriented way of implementing databinding.
Databinding with Windows forms 2.0 - This book by Brian Noyes explores various aspects of Databinding, both in complex and simple scenarios.
While the WinForms designer may not let you do this, have you tried setting up the binding in code? I imagine there is no problem binding a textbox to someCar.Tires[1].Pressure.

Categories