Winforms ComboBox User Control Binding - c#

I have a user control that inherited from Combobox control. I want to bind data in the constructor of the user control. but when I add it to form and run the project it shows duplicated items.
When I add control to my winform its add items in the Designer file of form and when I run project it added again in constructor of user control.
public partial class CheckSeriesBox : ComboBox
{
private static List<string> CheckSeries;
public CheckSeriesBox()
{
InitializeComponent();
CheckSeries = new List<string>();
SetCheckSeries();
this.Items.AddRange(CheckSeries.ToArray());
this.SelectedIndex = 0;
}
public static List<string> SetCheckSeries()
{
CheckSeries.Add("A");
CheckSeries.Add("B");
}
}

http://social.msdn.microsoft.com/forums/vstudio/en-US/3e35b534-7d3f-4832-8859-b5cb838bd62a/extended-combobox-adds-items-twice
public partial class CheckSeriesBox : ComboBox
{
private static List<string> CheckSeries;
public CheckSeriesBox()
{
InitializeComponent();
CheckSeries = new List<string>();
SetCheckSeries();
if (DesignMode)
{
this.Items.AddRange(CheckSeries.ToArray());
}
}
public static List<string> SetCheckSeries()
{
CheckSeries.Add("A");
CheckSeries.Add("B");
}
protected new bool DesignMode
{
get
{
if (base.DesignMode)
{
return true;
}
else
{
Control parent = this.Parent;
while ((parent != null))
{
System.ComponentModel.ISite site = parent.Site;
if ((site != null) && site.DesignMode)
{
return true;
}
parent = parent.Parent;
}
return false;
}
}
}
}

Related

When collection changed in ObservableCollection add new entries to ReactiveList

I have an ObservableCollection which getting filled from a TcpClient. When new data arrives (new Items are added), I want to create new Buttons inside an ItemsControl. It works the old way (with CollectionChanged) but I don't get it work with ReactiveUI.
I'm very new to ReactiveUI, and its quite hard for me to getting started. Could you may help me by putting me on the right path or maybe by providing some sample code?
The Idea:
public class ChooseMachineViewModel : ReactiveObject
{
public ReactiveList<Button> ButtonList { get; set; }
private Dictionary<ushort, Button> addressToButton;
//This one is normaly in another class and will be filled by a TcpClient
public readonly ObservableCollection<WWSS.Message.CUStatus> ControlUnitsStatus;
public ChooseMachineViewModel()
{
//TODO: Make this Reactive!
//The ButtonList for an ItemsControl
ButtonList = new ReactiveList<Button>();
//The Dictonary for addresses -> Button
addressToButton = new Dictionary<ushort, Button>();
//The ObservableCollection filled by a TCP Server
ControlUnitsStatus.CollectionChanged += ControlUnitsStatus_CollectionChanged;
}
private void ControlUnitsStatus_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (WWSS.Message.CUStatus stat in e.NewItems)
{
TryAddButton(stat);//When new Status arrive, try to create new button
}
}
if (e.OldItems != null)
{
foreach (WWSS.Message.CUStatus stat in e.OldItems)
{
TryRemoveButton(stat);//When Status removed, try to remove the button
}
}
}
private bool TryAddButton(WWSS.Message.CUStatus status)
{
if (!addressToButton.ContainsKey(status.Address))//if the Address is already in the dictonary don't create a button
{
var but = new Button { Content = status.Address.ToString() };
addressToButton.Add(status.Address, but);
ButtonList.Add(but);
return true;
}
return false;
}
private void TryRemoveButton(WWSS.Message.CUStatus status)
{
if (addressToButton.ContainsKey(status.Address))
{
ButtonList.Remove(addressToButton[status.Address]);
addressToButton.Remove(status.Address);
}
}
}
The trick was to use CreateDerivedCollection:
public class ChooseMachineViewModel : ReactiveObject
{
public IReactiveDerivedList<Button> ButtonList { get; set; }
public ChooseMachineViewModel(ObservableCollection<CUStatus> source)
{
addressToButton = new Dictionary<ushort, Button>();
ButtonList = ControlUnitsStatus.CreateDerivedCollection(status => new Button { Content = status.Address.ToString() },
status => !ButtonList.Any(button => button.Content.ToString().Equals(status.Address.ToString())));
}
}

How can I pair objects to radio buttons?

I'm working on a small form app, and I have "paired" my radio buttons with lists in a common class. The purpose of this was to turn on/off the corresponding list
public class myType
{
public RadioButton button { get; set; }
public ListBox list { get; set; }
}
I proceed to create these pairs through a for loop inside an array
for (int i = 0; i < broj_botuna; i++)
{
theArray[i] = new myType();
}
I use a common event handler for all the radio buttons:
private void test_CheckedChanged(object sender, EventArgs e)
{
var xx = sender as RadioButton;
//do stuff
positionInArray = Array.IndexOf(theArray, xx);
}
except that the last line of code "xx" should be of type "myType" and not "radioButton" that I managed to retrieve.
So could anyone tell me how do I get the reference from "radioButton" to "myType"? Or is there a better alternative?
You can use Array.FindIndex like:
var positionInArray = Array.FindIndex(theArray, b => b.button == xx);
You could create some constructs that allow you to easily associate your properties to the parent object if you wanted to.
This approach would allow you to always reference your parent type provided that you added a bit more code in your get's and set's.
static void Main()
{
myType item = new myType();
var button = new Button();
myType.button = button;
var list = new ListBox();
myType.list = list;
item = list.GetParent();
bool isSameButton = button == item.button;
bool isSameList = list == item.list;
Assert.IsTrue(isSameButton);
Assert.IsTrue(isSameList);
}
public class myType
{
private RadioButton _button;
public RadioButton button
{
get { return _button; }
set {
value.AssociateParent(this);
_button = value;
}
}
private ListBox _list;
public ListBox list
{
get { return _list; }
set {
value.AssociateParent(this);
_list= value;
}
}
}
public static class Extensions
{
private static Dictionary<object, object> Items { get; set; }
static Extensions()
{
Items = new Dictionary<object, object>();
}
public static void AssociateParent(this object child, object parent)
{
Items[child] = parent;
}
public static object GetParent(this object child)
{
if (Items.ContainsKey(child)) return Items[child];
return null;
}
}

Manipulating collection from the inside

I have a collection of panels which are highlighted when user clicks on them. I want to force them to behave as a set of radio buttons so only the one that is clicked on is highlighted and others aren't.
I guess that there must be a way to manipulate whole collection (set property to false) from the inside, because the event is triggered by one item from the collection. Is there a way for the one item to manipulate whole collection? This is such a common feature in applications so I guess there must be a pattern how to do it properly. Thanks.
You may store collection of your panels and handle required functionality as in following code snippet:
List<Panel> Panels;
private void Initialization()
{
Panels = new List<Panel>();
Panels.Add(pnl1);
Panels.Add(pnl2);
//add all your panels into collection
foreach(Panel Item in this.Panels)
{
//add handle to panel on click event
Item.Click += OnPanelClick;
}
}
private void OnPanelClick(object sender, EventArgs e)
{
foreach(Panel Item in this.Panels)
{
//remove highlight from your panels, real property should have other name than Panel.HighlightEnabled
Item.HighlightEnabled = false;
}
((Panel)sender).HighlightEnabled = true; //add highlight to Panel which invoked Click event
Application.DoEvents(); //ensure that graphics redraw is completed immediately
}
private void AddNewPanelIntoLocalCollection(Panel panel)
{
//here you can add new items to collection during program lifecycle
panel.Click += OnPanelClick;
this.Panels.Add(panel);
}
This is how I do it
public class SelectOne : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
private bool isSelected = false;
private HashSet<SelectOne> selecteOnes = null;
public bool IsSelected
{
get { return isSelected; }
set
{
if (isSelected == value) return;
if (isSelected && selecteOnes != null)
{
foreach (SelectOne so in selecteOnes)
{
if (so == this) continue;
so.IsSelected = false;
}
}
NotifyPropertyChanged("IsSelected");
}
}
public SelectOne() { }
public SelectOne(bool IsSelected) { isSelected = IsSelected; }
public SelectedOne(bool IsSelected, HashSet<SelectOne> SelecteOnes)
{
isSelected = IsSelected;
selecteOnes = SelecteOnes;
}
}
Eventually I did find a way to do this properly with only one delegate.
In class A I have a collection of objects B
List<B> b = new List<B>
class B, needs to have an unique ID and delegete for void metod with Id parameter
delegate void DeleteItemDelegate(int id);
class B
{
public int ID {get; set;}
public DeleteItemDeleate deleteThis {set; get;}
}
class A has a metod like this:
public void RemoveItem(int id)
{
for (int x = 0; x < b.Count; x++)
{
if (b[x].id == id)
{
b.RemoveAt(x);
}
}
}
when adding a new B object into List just add metod RemoveItem to B.deleteThis delegate
B bObject = new B();
bObject.deleteThis = RemoveItem;
b.Add(bObject);
Now all you need to do is add DeleteMe metod in B class
void DeleteMe()
{
// and call local delegate - pointing to metod which actually can manipulate the collection
deleteThis(id);
}

Using recursion to load controls into a Form

I have a process which uses recursion to generate controls from XML. The system is complicated. I've broken down as small as I can. The last Plugin is visible, the rest are not. I suspect GenerateControls() is broken. Why don't all the plugins display?
Form:
public partial class PdLoadingForm : Form
{
public PdLoadingForm()
{
InitializeComponent();
PhysDocDocument document = MockDocument();//Generate some mock data
GenerateControls(document.Nodes);//Generate controls using recursion.
}
private PhysDocDocument MockDocument()
{
PhysDocDocument document = new PhysDocDocument();
PhysDocNode outerNode = new PhysDocNode();
outerNode.Display = "outer Node";
//Generate 3 plugins. Each plugin generates a textbox. I only see 1 Textbox.
//I expect to see 3 textboxes.
for(int i = 0; i < 3; i++)
{
PhysDocNode innerNode = new PhysDocNode() { Display = "test" + i };
PhysDocNode innerNodeContent = new PhysDocNode() { Display = "IO" };
innerNodeContent.Plugins.Add(new Plugin());
innerNode.Nodes.Add(innerNodeContent);
outerNode.Nodes.Add(innerNode);
}
document.Nodes.Add(outerNode);
return document;
}
private void GenerateControls(List<PhysDocNode> children, CustomControl parent = null)
{
foreach (PhysDocNode node in children)
{
CustomControl parentControl = new CustomControl(node);
if (node.Nodes != null && node.Nodes.Count > 0)
GenerateControls(children: node.Nodes, parent: parentControl);
foreach (Plugin plugin in node.Plugins)
{
Control childControl = plugin.CreateUIControl();//Ask the plugin for a control
AddControl(childControl: childControl, parent: parentControl);
}
AddControl(childControl: parentControl, parent: parent);
}
}
private void AddControl(Control childControl, Control parent)
{
childControl.Dock = DockStyle.Top;
if(parent == null)//add to form
Controls.Add(childControl);
else//add to parent
parent.Controls.Add(childControl);
}
}
Plugin:
public class Plugin
{
[XmlAttribute]
public string type { get; set; }
public Control CreateUIControl()
{
TextBox testBox = new TextBox();
testBox.Text = "plugin";
return testBox;
}
}
CustomControl:
public class CustomControl: UserControl
{
public CustomControl(PhysDocNode nodeInfo)
{
InitializeComponent();
Label label = new Label();
label.Text = "Rtb..." + nodeInfo.Display;
label.Dock = DockStyle.Top;
contentPanel.Controls.Add(label);//just drop a panel on the user control in design view
}
Looking at the documentation, it seems that the Dock property manage the positionning of the label relatively to its parent.
You may try to specify the label position by, for example, setting its Top property's value to a multiple of its index in your control list.

GridView FocusedRowChanged - Child Class object

I need some help here.
I've created a child class called MyEditorRow from DevExpress EditorRow, and added 3 properties
public class myEditorRow : EditorRow
{
public myEditorRow()
{
}
private string inRowDescription = null;
public string RowDescription
{
get { return inRowDescription; }
set { inRowDescription = value; }
}
private bool inRequired = false;
public bool Required
{
get { return inRequired; }
set { inRequired = value; }
}
private bool inInherits = false;
public bool Inherits
{
get { return inInherits; }
set { inInherits = value; }
}
Second part of the code somewhere in the program adds instance of MyEditorRow to DevExpress VGrid Control.
vgcGrid.Rows.Add(Row);
My question is this: How can I link MyEditorRow class with DevExpress VGrid Control FocusedRowChanged event, so I can get my custom properties when row focus changes.
Thanks
The e.Row parameter is of the BaseRow type. So, to obtain an instance of the MyEditorRow object in the FocusnedRowChanged event handler, use the following code:
private void vGridControl1_FocusedRowChanged(object sender, DevExpress.XtraVerticalGrid.Events.FocusedRowChangedEventArgs e) {
if(e.Row is myEditorRow) {
myEditorRow row = ((myEditorRow)e.Row);
// your code here
}
}

Categories