I have a WPF window with a maintabWindow and several tabitems.
It normally works fine and the layout is this:
but when I BEFORE add the following window:
the result is this:
So the problem is related with the tabControl/tabItem refresh.
This is fairly obvious but even more because if I move the window or pass with the mouse on the a tabItem they get refreshed one by one.
I searched and found that here is a solution: http://geekswithblogs.net/NewThingsILearned/archive/2008/08/25/refresh--update-wpf-controls.aspx
so I added:
this.MainTab.Refresh();
this.tabItem1.Refresh();
this.tabItem2.Refresh();
this.tabItem3.Refresh();
this.tabItem4.Refresh();
this.tabItem5.Refresh();
but that didn't change a thing.
Thanx for any help
Ok so in the end it has a quite a weird behavious. If I do
for (int i = 0; i < tbcMain.Items.Count; i++)
{
tbcMain.SelectedIndex = i;
tbcMain.UpdateLayout();
}
it works. But I have to set the 1st tabitem so if I add
tbcMain.SelectedIndex = 0;
it doesn't.
So the solution was put a sleep and it works again.
for (int i = 0; i < tbcMain.Items.Count; i++)
{
tbcMain.SelectedIndex = i;
tbcMain.UpdateLayout();
}
System.Threading.Thread.Sleep(250);
tbcMain.SelectedIndex = 0;
But that is not elegant at all. If anyone has a better solution pls let me know it.
Btw adding the tbcMain.SelectedIndex = 0; on the loaded event of the mainWindow is of no use.
You should be able to set your SelectedIndex first, and without having to include it in your loop:
tbcMain.SelectedIndex = 0;
Then, basing it off of your response, you should be able to either just do .UpdateLayout() on each of your TabItems:
MainTab.UpdateLayout();
tabItem1.UpdateLayout();
tabItem2.UpdateLayout();
tabItem3.UpdateLayout();
tabItem4.UpdateLayout();
tabItem5.UpdateLayout();
Or you should be able to do something like this in your loop:
MainTab.UpdateLayout();
for (int i = 0; i < tbcMain.Items.Count; i++)
{
TabItem tbi = (TabItem)this.FindControl("tabItem"+i);
tbi.UpdateLayout();
}
Updating/refreshing should have nothing to do with setting the selected one. Including the selection of the tab within the loop to i was your problem - not a race condition. Set the tbcMain.SelectedIndex = 0 outside of your loop and you should be fine. Sometimes, however, this doesn't work and you need to set it with Dispatcher:
Dispatcher.BeginInvoke((Action)(() => this.tbcMain.SelectedIndex = 0));
There's a write up/comments on a separate thread regarding why it needs to be sent to Dispatcher:
How to programmatically select a TabItem in WPF TabControl
Though, unfortunately for me, I had a similar issue where I was trying to refresh a ListView on a subtab. Neither .UpdateLayout(), nor .InvalidateVisual() (as I saw on this thread) worked. I just had to rebind my grid in the button event I was using on my main page, so that when the tab was clicked, it was refreshed manually. I added an x:Name property on the tab so I could call it using "dot" syntax, and it exposed the ListView. I simply added the DataTable of results back to that ListView's DataContext.
Related
I am kind of newbie and I have an issue with ASP:Button controls.
There is about 60 buttons on the page, typical XAML looks like this:
<asp:Button class="tile" ID="Button1" runat="server" Text="Domains"/>
I need to iterate through all of the buttons on the page to change properties and I don't want to do it one by one.
I've found many suggestions here and there, but nothing works. My code behind is:
for (int i = 1; i < 59; i++)
{
String butt = String.Format("Button{0}", i);
var btn = FindControl(butt);
btn.Visible = false;
}
Error is that there is no object reference. btn is null.
I tried to inspect element in running application and it says ID of element is "MainContent_Button1" - tried that too, does not work. Other thing I tried is
foreach(var button in this.Controls.OfType<Button>())
{
button.Visible = false;
}
I came to conclusion that asp:button is a) not a control of button type b) its ID is somehow generated when the application is run and therefore there is no control with id Button1 to be found.
Can anyone please explain that to me? I'd really like to understand why is it behaving like that and what exactly is the purpose of this behavior.
Thanks
Edit: I even tried to remove the loop completely and modify one specific button using FindControl method. Does not work either.
var btn = FindControl("Button1");
btn.Visible = false;
result: System.NullReferenceException: 'Object reference not set to an instance of an object.'
It looks like you are using a Master Page. Using FindControl on a Master Page works slightly different than on a normal page.You first need to find the correct ContentPlaceHolder in which the Buttons are located and use FindControl on that ContentPlaceHolder.
ContentPlaceHolder cph = Master.FindControl("MainContent") as ContentPlaceHolder;
for (int i = 1; i < 9; i++)
{
String butt = String.Format("Button{0}", i);
var btn = cph.FindControl(butt);
btn.Visible = false;
}
So here is the story - I have 2 DataGridViews - one of them is used as a display, the other one is user for editing or adding new entries. I don't use bindings on the edit one. When I am creating new entry I am just extracting the cells' values and passing them to an object. When I am editing though comes the problem.
The edit consists of 2 parts - one is to select the entry to be edited and display it on the second DGV. This is done with SelectionChanged event and the code is bellow. Then when editing is done it should just publish the new task the same way as creation. The thing is that when I am doing the edit and I come to the moment when I have to select from one of my cells - a ComboBoxCell - and I make a selection everything freezes. I cannot click anything else than this ComboBox until I press Esc - which obviously reverts the choice.
Why is this freeze happening and what causes it only when the data is cloned from the first DGV, but is okay when creating a brand new row? I am using VS2012 by the way and this is a windows forms application
Here is the code for duplication of the selected task - this method is the only thing in the DGV1's SelectionChanged Event handler:
public void createTemplateTaskToBeEditted(Form1 form1, ApplicationControl appControl)
{
form1.dg_templateView.Rows.Clear();
for (int i = 0; i < form1.dg_taskView.SelectedRows.Count; i++)
{
if (form1.dg_taskView.SelectedRows[i].Cells[0].Value == null)
{
form1.dg_taskView.SelectedRows[i].Cells[0].Value = false;
}
int index = form1.dg_templateView.Rows.Add();
form1.dg_templateView.Rows[index].Cells[0].Value =
form1.dg_taskView.SelectedRows[i].Cells[0].Value.ToString();
form1.dg_templateView.Rows[index].Cells[1].Value =
form1.dg_taskView.SelectedRows[i].Cells[2].Value.ToString();
form1.dg_templateView.Rows[index].Cells[2].Value =
form1.dg_taskView.SelectedRows[i].Cells[3].Value.ToString();
form1.dg_templateView.Rows[index].Cells[3].ValueType = typeof(ComboBox);
form1.dg_templateView.Rows[index].Cells[3].Value =
form1.PopulateAssignToComboBox(appControl.GetAllowedMembers(form1));
form1.dg_templateView.Rows[index].Cells[4].Value =
form1.dg_taskView.SelectedRows[i].Cells[5].Value.ToString();
form1.dg_templateView.Rows[index].Cells[5].Value =
form1.dg_taskView.SelectedRows[i].Cells[6].Value.ToString();
form1.dg_templateView.Rows[index].Cells[6].Value =
form1.dg_taskView.SelectedRows[i].Cells[7].Value.ToString();
form1.dg_templateView.Rows[index].Cells[7].Value =
form1.dg_taskView.SelectedRows[i].Cells[8].Value.ToString();
form1.dg_templateView.Rows[index].Cells[8].Value =
form1.dg_taskView.SelectedRows[i].Cells[9].Value.ToString();
form1.dg_templateView.Rows[index].Cells[9].Value =
form1.dg_taskView.SelectedRows[i].Cells[10].Value.ToString();
form1.dg_templateView.Rows[index].Cells[10].Value =
form1.dg_taskView.SelectedRows[i].Cells[11].Value.ToString();
form1.dg_templateView.Rows[index].Cells[11].Value =
form1.dg_taskView.SelectedRows[i].Cells[12].Value.ToString();
}
}
I have a code which spawns a button(gameobject) with presets everytime I press save.
This button is then saved into a List of gameobjects which I then use to select or deselect them.
I tried to make it so that only 1 button in the list can be selected at a time.
It's working to some degree as If i press the button before the current selected one it works. But if i press any button after the currently selected one it is unable to deselect it.
Can anyone help me with this?
public List<GameObject> presetButtons = new List<GameObject>() ;
This is the list of Buttons
void Update () {
for (int i = 0; i < presetButtons.Count; i++) {
if(presetButtons[i].GetComponent<CamUIButtonHandler>().isSelected){
indicator = i;
topView.isSelected = false;
}
}
for (int u = 0; u < presetButtons.Count; u++) {
if(u != indicator)
presetButtons[u].GetComponent<CamUIButtonHandler>().isSelected = false;
}
}
This is supposed to deactivate the other buttons once 1 is selected.
I'm guessing that there is something that causes it to not be able to overwrite the currently selected button however I can't seem to find the issue.
Can anyone help me with this? much thanks
This sounds to me like a good place to use UGUI's Toggle And ToggleGroup features. Put a toggle component on each button. Then set each of those buttons' group properties to be the same ToggleGroup. Of course if you aren't using UGUI then this won't be possible.
I have added buttons to a grid layout I created. Here is the code for that.
int nodeIndex = 0;
for (i = 0; i < usedRows; i++)
{
for (j = 0; j < cols; j++)
{
this.tableLayoutPanel1.Controls.Add(nodes[nodeIndex++], j, i);
}
}
Later on in the application I want to be able to change the color of a button at a specified position. Basically change the back round color of the button at position i,j. How would I get access to that specific button? I am using winforms. Is there something like
button = this.tableLayoutPanel1.Controls.GetChildAtPosition(j, i)
You can use something along these lines.
button = this.tableLayoutPanel1.GetControlFromPosition(j, i);
button.BackColor = Color.BLACK;
So first you want to able to find the control and conveniently there is a method called FindControl() that can do just that
MSDN link for reference: http://msdn.microsoft.com/en-us/library/system.web.ui.control.findcontrol(v=vs.110).aspx
Second you want to be able to change the color of the button once you find it.
For buttons you probably want to use the BackColor property.
Again MSDN link for reference:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.backcolor(v=vs.110).aspx
The trick is going to be finding the control and then working with that control as an object to change the color. Don't forget that you can cast the control to a button type once you find it, which should give you access to the BackColor property.
I'm currently working on something that is probably done in plenty of examples out there. But after some searching I can't find anything.
I'm working with WPF tab control and I'm trying to recreate some basic functionality (which you see in all internet browsers nowadays) to add a new tab by clicking a '+' tab which is the last listed tab.
I already have the '+' tab which adds a new tab. My problem is, I want to move the '+' tab after the new tab (so its the end tab again) and switch view to the new tab that has just been created.
I thought something like:
void tiNewTab_Add(object sender, EventArgs e)
{
int idx = tabControl1.Items.Count;
tabControl1.SelectedIndex = idx - 1;
TabItem ti = new TabItemKPI();
tabControl1.Items.Add(ti);
tabControl1.Items.MoveCurrentToLast();
}
...would work but no luck :(
Try something like this:
tabControl1.Items.Insert(tabControl1.Items.Count-1,ti);
This will do because you always have at least one TabItem (the + one)
Then select the second last one by
tabControl1.SelectedIndex=tabControl1.Items.Count-2;
Not tested, but following should work:
int idx = tabControl1.Items.Count;
tabControl1.SelectedIndex = idx - 1;
TabItem ti = new TabItem();
tabControl1.Items.Insert(tabControl1.Items.IndexOf(tabControl1.Items.Last()), ti);