custom-made UserControl property binding in WinForms - c#

I've a custom-made user control:
public class CustomUC : UserControl
{
[Bindable(true)]
private string PropertyX { get { ... } ; set { ... }; }
}
I'm using it from another form. On this form I'm using a DataSource.
The problem is that I'm unable to figure out how to bind this PropertyX to some field of my DataSource.
EDIT
My DataSource is a System.Windows.Forms.BindSource object I've created on design-time. I've set a class to this datasource in order to be linked to a ClassA. This class has a property Notes I'd like to bind to CustomMadeUCPropertyX...

You should try following way to bind property by coding:
object.DataBindings.Add("PropertyX", YourDataSrouce, "columnname in your datasource")

Related

How to get EditValue from CheckedComboBoxEdit

I have a DevExpress CheckedComboBoxEdit on my form.
In designer i had binded this control with BindingSource.
In BindingSource i have objects
public class MyClass
{
public int Id {set;get;}
public string Name {set;get;}
}
I set DisplayMember as Name and set ValueMember as empty so i expect that i got whole object from EditValue.
Now i want to bind this control with my view model
public class MyViewModel{
***
public List<MyClass> TestList{set;get;}
***
public MyViewModel(){
TestList = new List<MyClass>();
}
}
After i run app with this form. Select values in control.
But after i see that MyViewModel.TestList is empty.
And CheckedComboBoxEdit.EditValue contains list of MyClass.Name what is i setted as DisplayMember.
It is possible to bind CheckedComboBoxEdit to property and make taht EditValue retunr whole object?

WPF Bind once and never update?

I have a ListView and a GridView that lists users in an application by names. Whenever the user selects an user to edit, I add a new tab to a TabControl, and bind all editable properties to the WPF controls.
However, when the user is editing in the Edit Tab, the information in the List (specifically, the name field) is also being updated.
Currently I'm making a copy of the object to be edited and leaving the original so it doesn't update the ListView, but isn't there a better/easier way to do this?
I've tried setting the Binding Mode=OneWay, didn't work, and also UpdateSourceTrigger=Explicit in the GridView but also didn't work.
Is there any easier way to do this?
Edit: The way I implemented my INotifyPropertyChanged class is part of the issue, since I have this:
public partial class MyTabControl : UserControl
{
public MyTabControl()
{
InitializeComponent();
//Here, DataContext is a List<Users>
//Users being my Model from the Database
//Some of it's properties are bound to a GridView
//User doesn't implement INPC
}
public void OpenTab(object sender, RoutedEventArgs e)
{
User original = (sender as Button).DataContext as User;
// - This will create a new ViewModel below with the User I'm sending
MyTabControl.AddTab(original);
}
}
And my ViewModel of Users is:
public class UserViewModel : INotifyPropertyChanged
{
public User Original { get; private set; }
public string Name { get { return Original.Name; } set { Original.Name = value; OnPropertyChanged("Name"); } }
public UserViewModel(User original)
{
Original = original ?? new User();
}
// - INPC implementation
}
Since my ViewModel is the one reporting the property changes, I didn't expect my original User to report it as well to the GridView.
The Mode=OneWay causes the information flow to go from the bound data entity to the target UI property only, any change to the UI property will not be bound back.
The reason why the UI content is changing is because the underlying property is read/write (i.e. has a getter and a setter) and is notifying any value change (due to the implementation of the INPC interface).
Presuming that it is a list of User objects you've bound to the GridView, you have two simple options to fix this. Which one is best depends on how much scope for change you have:
change the current Name property on the User object, remove the setter for it. Replace the setter with a method to set the property (i.e. SetUserName(string name)) which then sets the private member variable. Or pass the name as an argument to the constructor of the User entity.
create a new property with only a getter which returns the name and set your binding to that; i.e. public string UserName { get { return Name; }}. As there is only a getter there will be no notification of this property, so if the name does change it won't be propagated via this new property.

C# WPF MVVM ComboBox Binding

First of all, what I'm trying to do is a "simple" binding of a ComboBox to my source.
The structure is something like:
public class Data
{
public ObservableList<string> List {get;set;}
public string Selected {get;set;}
}
Also, it implements INotifyPropertyChanged interface.
My problem is, i found several solutions to do this via XAML, unfortunately i can't do it with XAML since my ComboBoxes have to be generated during runtime.
So my question is, how i can bind my ComboBox to Data.List, and also the selected item (value?) to Data.Selected, and this one should be TwoWay so my Data class knows that something was selected. Keep in mind this has to be through c# code (XAML is no option unfortunately).
Thanks in advance. :)
It's pretty easy. Assuming, that Data has properties instead of fields:
public class Data
{
public Data()
{
List = new ObservableCollection<string>
{
"Apple", "Orange", "Lime"
};
}
public ObservableCollection<string> List { get; private set; }
public string Selected { get; set; }
}
you can write this:
var comboBox = new ComboBox
{
DataContext = new Data()
};
comboBox.SetBinding(ComboBox.ItemsSourceProperty, new Binding("List"));
comboBox.SetBinding(ComboBox.SelectedItemProperty, new Binding("Selected")
{
Mode = BindingMode.TwoWay
});
To add ComboBox into visual tree, just call proper method for the container. E.g., this will work with any ContentControl (like Window):
AddChild(comboBox);
how i can bind my combobox to Data.List, and also the selected item (value?)
Create a custom composite user control which contains the combobox. Map the combobox's properties to two dependencies properties created on the custom control, one to load the data and the other to provide an on demand selected item's data. Any plumbing needs are done inside the codebehind which ultimately provides all the magic.
Then you can create/bind this control dynamically in codebehind as needed in the other page you are working on.
Sounds like a sort of "recursive binding". If your combos are in a container control, what you need is bound the container to a collection of your single combo model, so each view in the ItemsControl will be bound to a single combo model.

exposing the combobox Items property in a usercontrol

I have a user control that contains a combobox. I want to be able to edit the Items property for the combo box but im not really sure how to do that. I've tried adding the Items property to my user control class but im not sure what the value is thats returned when you set the property in the properties menu of visual studio. I have the property setup like this:
[Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design",
"System.Drawing.Design.UITypeEditor, System.Drawing")]
public ComboBox.ObjectCollection Items
{
get
{
return this.comboBox.Items;
}
set
{
this.comboBox.Items.Add(value);
}
}
Wrap the Items property of your UserControl's ComboBox in a property like this:
[Description("The items in the UserControl's ComboBox."),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design", typeof(System.Drawing.Design.UITypeEditor))]
public System.Windows.Forms.ComboBox.ObjectCollection MyItems {
get {
return comboBox1.Items;
}
}
The EditorAttribute in the property specifies the UI element used for changing the property in the designer.
Try adding two methods for adding and removing ComboBox items:
public void AddItem(Object item)
{
this.comboBox.Items.Add(item);
}
public void RemoveItem(Object item)
{
this.comboBox.Items.Remove(item);
}

Binding Dependency Properties

So here I come creating a user control. It consists of a treeview dropping down from a combobox.
Actually, there is a button with a control (DropTree) dropping down from its contextmenu. So I have a control DropTree.
public partial class DropTree : UserControl
{
public TreeView TreeView
{ get{return treeView;} }
public DropTree()
{ InitializeComponent(); }
}
to simplify it, I made the TreeView control public, then I have my main control which is called ComboTreeView.
Now I need to represent some treeview properties in it, so I define several dependency properties:
public static DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(ComboTreeView), new FrameworkPropertyMetadata { Inherits = true, IsNotDataBindable = false, DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
and in constructor it is:
public ComboTreeView()
{
InitializeComponent();
TreeViewControl.SetBinding(TreeView.SelectedItemProperty, new Binding("SelectedItem") { Source = this, Mode = BindingMode.TwoWay });
}
and it all seems ok, until i run it. It crashes saying that SelectedItem cannot be binded to data. I don't understand?
The same goes for ItemsSource and SelectedValue... but only SelectedValuePath property defined this way goes fine.
Can anybody help? Or is there any other way to bind it correctly?
PS: by the way, I need to use DataBinding for ComboTreeView in my code later.
Try to set the Binding on SelectedValue instead of SelectedItem.
TreeView.SelectedItem is a readonly property. You can't set it, whether explicitly or through binding. In order to select a node in a TreeView, you must set the TreeViewItem.IsSelected property to true.

Categories