c# store multiple splitter position in user.config - c#

In my winform there are some Splitter to separate some datagridviews, is there a way to store (and recover) the splitter position into the user.config?
I wish avoid to add a setting with a different name for each splitter if it's possible.
thanks in advance

I came up with something you may be able to use. A few things about this example:
I used SplitContainer, but I'd imagine you could adapt this pretty easily.
I only scan the form's list of controls - this method won't pick up all SplitContainer (you'll probably need to do that recursively).
This assumes you have a user setting called SplitterPositions of type string.
This doesn't take into account future changes to the form (i.e. rearranging controls, adding new sections, removing existing sections, etc.), so it's a bit fragile in that regard.
I would personally recommend assigning names to your Splitters (or SplitContainers, depending on which type you're using) since that should shield you from the issues I mentioned.
In any event I hope this helps.
public Form1()
{
InitializeComponent();
Closing += Form1_Closing;
ApplySavedSplitterData();
}
void Form1_Closing(object sender, CancelEventArgs e)
{
SaveSplitterData();
}
private void SaveSplitterData()
{
Settings.Default.SplitterPositions = string.Join(";",
Controls.OfType<SplitContainer>()
.Select(s => s.SplitterDistance));
Settings.Default.Save();
}
private void ApplySavedSplitterData()
{
if (string.IsNullOrEmpty(Settings.Default.SplitterPositions))
{
return;
}
var positions = Settings.Default.SplitterPositions
.Split(';')
.Select(int.Parse).ToList();
var splitContainers = Controls.OfType<SplitContainer>().ToList();
for (var x = 0; x < positions.Count && x < splitContainers.Count; x++)
{
splitContainers[x].SplitterDistance = positions[x];
}
}

You can use the library from the article User Settings Applied to save the splitter position into the user settings.
Additionally you can persist the form size/location and any custom form setting.

Related

My Ui hide Ads. I want how to find Ads's canvas

my situation..
private void Win()
{
OpenNextStage();
CheckGameCount();
Managers.Ui.SetSmallPopup(UiManager.SmallPopupUi.ClearPopup);
_uiGamePopup.SetLineOnOff(false);
}
private void CheckGameCount()
{
_gameCounter++;
if (_gameCounter >= 1)
{
Managers.Ads.ShowInterstitial();
_gameCounter = 0;
}
}
this is my code.
my code make popup object after show Ads.
i want control this Ads's canvas, and change sort order.
but Ads object name is 768x1024(Clone). it's uneasy to be convinced of that always have that name.
how to find that object?? or is there any good way?
i use GameObject.Find() but this is not good way i think.
Go to GoogleMobileAds Folder and set sort order of different ad canvases as in:

How can I control the display order of child Forms in a MDI Form

When I use an MDI Form I have a problem. My source code just like this:
private void menuItem1_Click(object sender, EventArgs e)
{
Form[] charr = this.MdiChildren;
int i = 0;
foreach (Form chform in charr)
{
chform.Dock = DockStyle.Top;
}
this.LayoutMdi(System.Windows.Forms.MdiLayout.TileHorizontal);
}
The numbers of child Forms is more then 3. In order to display them correctly after the LayoutMdi() method is called, I had to set the Dock property of all child Forms to DockStyle.Top.
After calling LayoutMdi(MdiLayout.TileHorizontal), clicking the Title Bar of the first child Form, this child Form is displayed at the bottom of the MDI parent automatically.
I want that the clicked child Form maintains it's original position.
Is there any idea for this question?
Looking at the linked question - where it was suggested to set the Dock property to adjust the MDIChild Forms position - and the currently reported behavior, it is probably preferable to define the layout the MDIChild Forms without the help of automatic feature.
This allows to perform any layout logic that seems appropriate.
In the example, the MDIChildren.Height is calculated in relation to the MDIParent.ClientSize.Height and the number of opened MDIChildren, then multiplied by a values: in the sample code by 2, twice the base measure.
This Multiplier allows to define the Horizontal Tile Height of the MDICHildren quite precisely. Of course, you could implement some other logic that applies the multiplier only when there are at least 3 opened MDIChildren.
All the MDIChildren are re-sized to match the MDIParent.Width and the calculated Height, then ordered by Name and positioned from top to bottom.
Set different values of HorizontalTileHeightMultiplier to see how the MDIChildren are positioned in the MDIParent.ClientArea (MdiClient).
This multiplier could also be used as a custom Property in the Application, available to its Users allowing a custom tiling of the Forms.
The layout code is provided as a private method, so it can be easily used in different event handlers to perform/maintain the selected layout (the MDIParent.Resize, for example).
This method can also be easily adapted to replace the MdiLayout.TileVertical if required.
private float horizontalTileHeightMultiplier = 2;
private void menuItem1_Click(object sender, EventArgs e)
{
TileHorizontal()
}
private void TileHorizontal()
{
int openedForms = Application.OpenForms.Count - 1;
if (openedForms < 2) return;
int startLocation = 0;
int childrenHeight =
(int)((ClientSize.Height / openedForms) * horizontalTileHeightMultiplier);
List<Form> children = MdiChildren.OrderBy(f => f.Name).ToList();
foreach (Form child in children)
{
child.Size = new Size(ClientSize.Width - SystemInformation.VerticalScrollBarWidth - 4, childrenHeight);
child.Location = new Point(0, startLocation);
startLocation += childrenHeight;
}
}

C# ComboBox disable highlighting

I have custom ComboBox, where DropDownStyle = ComboBoxStyle.DropDown;.DropDown style is set because I want to set the Text property of the ComboBox to something outside the list of values. Everything works good, except that ComboBox is highlighting the text when it's left and when I click on the combobox editing is avaible. How can I cope with this?
To illustrate:
First Picture is where everything looks good, second is the highlight situation, third editing is on.
Try un-selecting the text after the DropDown closes:
void comboBox1_DropDownClosed(object sender, EventArgs e) {
this.BeginInvoke(new Action(() => { comboBox1.Select(0, 0); }));
}
If you are referring to disabling the highlighting and editing, then you might want to consider setting the DropdownStyle property to DropdownList.
yourComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
Tricky problem to solve. It seems to be from the Resize event. There are a lot of solutions that do something similar to this, but none that I've seen worked for me until I tried this. (This is a solution that does not require inheritance from ComboBox; inheriting is probably a much more straight forward solution, but requires you to always use your inherited class and never the actual ComboBox class.)
comboBox.Resize += (s, e) => {
if (!comboBox.IsHandleCreated)
return; // avoid possible exception
comboBox.BeginInvoke(new Action(() => comboBox.SelectionLength = 0));
};
Set the selection length to zero to get rid of the highlight, but when? Other examples do it in other places, but the problem seems to be specifically caused by Resize, so doing it after Resize fixes it consistently, at least for me. (Can still see it flicker when you resize the window though, but it always ends up ok.)
BeginInvoke ensures that it happens sufficiently after Resize to work, and the check for IsHandleCreated prevents it from being called before the handle is created, in which case BeginInvoke would throw an exception.
This slightly more complex version includes some checks to prevent a focused control from losing highlight, since it actually should have it. It also doesn't fire if the parent doesn't exist yet, or if the parent does not have an active control yet, both signs that things are too early.
comboBox.Resize += (s, e) => {
if (!comboBox.IsHandleCreated)
return;
comboBox.BeginInvoke(new Action(() => {
var parent = comboBox.FindForm();
if (parent == null)
return;
if (parent.ActiveControl == null)
return;
if (parent.ActiveControl == comboBox)
return;
comboBox.SelectionLength = 0;
}));
};
I tried to make a version that would 'preserve' the selection length rather than always set it to zero, but I couldn't get it to synchronize properly. Many Resize events can fire before the BeginInvoke delegates start to fire, so the preserved value will always be overwritten by the broken one. I tried saving them all in a Queue or Stack, but in both cases, I was unable to reverse the ordering (not really sure why, since that makes no sense).
To solve the same I have tried almost EVERYTHING:
setting the DropdownStyle property to DropdownList
this.BeginInvoke(new Action(() => { comboBox1.Select(0, 0); }));
combobox1.SelectionLength = 0;
changing comboBox.TabIndex
Not tried SendKeys.Send("{ESC}"); because it is not a reliable solution
Nothing helped.
The only stable and working solution was to move a focus on another Label control:
label.Focus();
You could also hide that label.
I know this post is old but recently I have the same problem with combobox.
Situation : I have an editable combobox which propose complete words when user write some letters.
But when I want to type a letter, combobox auto highlight the text and the next letter auto replace the previous.
Solution : I use a textbox to avoid any highlight like that:
<ComboBox IsTextSearchEnabled="False" IsEditable="True" x:Name="CMB_ClientName"/>
<TextBox Text="{Binding ElementName=CMB_ClientName, Path=Text}" TextChanged="ComboBoxChange" x:Name="TXT_ClientName"/>
And I generate the textbox TextChanged event :
private void ComboBoxChange(object sender, TextChangedEventArgs e)
{
//Clear ComboBox items
CMB_ClientName.Items.Clear();
//Auto Open DropDownList
CMB_ClientName.IsDropDownOpen = true;
//Get data from database (use entity framework 6.x)
dbEntity.Client.Load();
//Attribute Data to variable
var clients = dbEntity.Client.Local;
foreach (Client client in clients)
{
//If data begin with the texbox text, the data is add to the combobox items list.
if (client.Nom.ToLower().StartsWith(TXT_NomClient.Text.ToLower()))
{
CMB_ClientName.Items.Add(client.Nom);
}
}
}
I know this solution isn't realy beautifull, but it is for me the easiest solution to avoid highlight text and all the solutions in this post don't work for me.
I hope this solution will be helpfull, thanks for reading.
Math.
Ps: My apologies, my English is not very good. I hope you will understand me correctly.
Nothing worked for me ( I want the form to load with no highlighting in any combobox) until I set the combobox property TabStop to false. This meant that one of my buttons took the tab highlight which I didn't like so I set them all to false for start up and adjusted them programatically as needed.
I know this is an old thread, but my solution is similar to that of the others, but relies on the Form.ResizeEnd event. In its event handler, I iterate through the ComboBoxes and set ComboBox.SelectionLength to 0.
private void Form_ResizeEnd(object sender, EventArgs e)
{
foreach(ComboBox comboBox in parentControl.Controls.OfType<ComboBox>
{
comboBox.SelectionLength = 0;
}
}
This is what worked for me:
Set DrawMode to OwnerDrawFixed
Set cbxSubsystems.DrawItem event to the function below
private void cbxSubsystems_DrawItem(object sender, DrawItemEventArgs e)
{
Color BgClr;
Color TxClr;
if( (e.State & DrawItemState.ComboBoxEdit) == DrawItemState.ComboBoxEdit )
{
// Do not highlight main display
BgClr = cbxSubsystems.BackColor;
TxClr = cbxSubsystems.ForeColor;
}
else
{
BgClr = e.BackColor;
TxClr = e.ForeColor;
}
e.Graphics.FillRectangle(new SolidBrush(BgClr), e.Bounds);
TextRenderer.DrawText(e.Graphics, cbxSubsystems.Items[e.Index].ToString(), e.Font, e.Bounds,
TxClr, BgClr, TextFormatFlags.Left | TextFormatFlags.VerticalCenter );
}

Is there a simple method to get coordinates of a particular item in a checkedlistbox?

I am making a simple class extending CheckedListBox that just adds a small textbox to the right of an item when it is checked. My issue is finding a good way to place the box at the correct location.
I had initially though I could use the Controls.Find() along with the ItemCheckEventArgs index to get the coordinates of the checkbox in question, and move to the right edge of the column from there. However, that did not work, and a brief look through the CheckedListBox class seemed to show that it does not actually contain any CheckBox controls, but merely draws images of them.
I then came up with the following method:
void CreateAmountBox(int index)
{
int itemsPerCol = Height/ItemHeight;
int x = GetColumn(index, itemsPerCol)*ColumnWidth - boxWidth;
int y = (index % itemsPerCol)*ItemHeight - offset;
System.Windows.Forms.TextBox NewAmountTextBox = new System.Windows.Forms.TextBox();
NewAmountTextBox.Location = new System.Drawing.Point(x, y);
NewAmountTextBox.Name = Items[index] + "Amount";
NewAmountTextBox.Size = new System.Drawing.Size(20, boxWidth);
Controls.Add(NewAmountTextBox);
}
where GetColumn(...) returns the column of the given index (from the CheckEventArgs). This works, but it feels like a hack and is not very readable.
Two other ideas I thought of:
1) I could just create all the TextBoxes at the start, and simply hide them until they are needed. Controls like these are all created dynamically throughout the rest of the program however, and I don't want these ones to be the odd exception. It also means that some more functionality needs to be added for cases when an item is added or removed.
2) I could use mouse position, which of course won't work if the input is via keyboard. I don't anticipate it ever being so, but best not to leave that possibility.
With some googling, the only other way I found of possibly doing this was using the ListBoxItem and TranslatePoint method, but I haven't gotten that to work, and I'm unsure as to whether it even can with a CheckedListBox instead of a ListBox.
So, is there a simple way of finding the x and y of the checked item that I don't know of? Or am I limited to simply extracting the x and y declarations above into a method and leaving it there?
You can just use the GetItemRectangle function to accomplish that:
void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) {
Rectangle r = checkedListBox1.GetItemRectangle(e.Index);
TextBox newAmountTextBox = new TextBox();
newAmountTextBox.Location = new Point(r.Left, r.Top);
//...
}

Switching Panels on button event

I have a row of panels on my WindowsForm which have two buttons on each, Move Up and Move down. I want it so that when the user clicks down it switches the current panel with the panel beneath it essentially taking its place. (swapping them over). I have 10 instances of the same panel so something simple like the below isnt working because all the panels are called DataPanel. Any help is appreciated.
private void MoveDownEnabled_Click(object sender, EventArgs e)
{
Point temp = DataPanel.location;
DataPanel.Location = Panel2.Location;
Panel2.Location = temp;
}
I would recommend storing the Panel in a collection, for a start. This will make the code for accessing the next panel, very clean.
ArrayList panels = new ArrayList();
panels.add(panel);
panels.add(panel2);
panels.add(panel3);
ANd also keep a value, index, to show where in the list you're up to.
private int index = 0; // Set it to a default value.
Then ammend your button click code:
private void MoveDownEnabled_Click(object sender, EventArgs e)
{
Panel Current = panels.get(index);
if(index < panels.Count)
{
// Grab the next item.
Panel Next = panels.get(++ index);
// And this part is up to you!
}
}
You seem to have the right idea with how you're swapping them around, so I think now I've set this up for you, you can work the rest out for yourself.
Don't use your variable name to differentiate controls at runtime, use their properties or their instances. In this case, you can use the Panel's Name property to differentiate, or its Tag property which can hold an object type. Also, I recommend storing the Panels in a collection such as a List so that they can be iterated and accessed easily.
For example (as a general idea)
//won't get nested panels but sounds like you don't need that
var listOfPanels = this.Controls.OfType<Panel>().ToList();
//access the panel you want by name
Panel pnl = listOfPanels.Where(x => x.Name == "panelName").FirstOrDefault();
In your case, your Panel events will be send the panel as the sender in your event handler.
private void MoveDownEnabled_Click(object sender, EventArgs e)
{
Panel selectedPanel = sender as Panel;
if(selectedPanel != null)
{
Point temp = DataPanel.location;
DataPanel.Location = selectedPanel.Location;
selectedPanel.Location = temp;
}
}
I think a simple swap method should do:
public void SwapPanels(System.Windows.Forms.Panel pnl1, System.Windows.Forms.Panel pnl2)
{
var localtion1 = pnl1.Location;
var location2 = pnl2.Location;
pnl2.Location = localtion1;
pnl1.Location = location2;
}
if you want to swap any two panels, just call this method to swap them. if you have many panels, just store them in a list or so and swap them freely.

Categories

Resources