I have a list box which is bound to a Service. It loads fine and allows me to select an item and moves through to second page.
The Second page loads a new observable collection from the same service and uses the selected Item from previous page to load a new listbox with a data filter.
This second listbox allows for a further selection to load a details page based on this selection. The error I have is that the second listbox loads and automatically selects the first item in the list. Upon pushing the back button it loads the second listbox with no selection made.
Can someone please tell me how to stop the automatic selection in my second listbox? Code details below.
First Listbox code including sender
void ServiceReference1Client_GetMensleaderListCompleted(object sender, GetMensLeaderListCompletedEventArgs e)
{
if (e.Error != null) { MensHeading.Text = "Connect to Data"; return; }
ObservableCollection<Mens_Leaders> mensLeaders = e.Result;
this.mensRankings.ItemsSource = mensLeaders;
}
private void mensRankings_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (mensRankings.SelectedItem != null)
{
Mens_Leaders SelectedPlayer = mensRankings.SelectedItem as Mens_Leaders;
_SelectedMensPlayer = (sender as ListBox).SelectedItem;
NavigationService.Navigate(new Uri("/Pages/PlayerProfile.xaml", UriKind.Relative));
FrameworkElement root2 = Application.Current.RootVisual as FrameworkElement;
root2.DataContext = _SelectedMensPlayer;
}
}
Page where second list loads
private void LoadPlayerList()
{
Service1Client ServiceReference1Client = new Service1Client();
ServiceReference1Client.GetTournamentListCompleted += new EventHandler<GetTournamentListCompletedEventArgs>(ServiceReference1Client_GetTournamentListCompleted);
ServiceReference1Client.GetTournamentListAsync();
FrameworkElement root2 = Application.Current.RootVisual as FrameworkElement;
var currentPlayer = root2.DataContext as ATP_Tennis_App.TennisService.Mens_Leaders;
_SelectedPlayer = currentPlayer;
_selectedPlayerTournamentsWon = currentPlayer.Name;
}
void ServiceReference1Client_GetTournamentListCompleted(object sender, GetTournamentListCompletedEventArgs e)
{
if (e.Error != null) { return; }
ObservableCollection<Tournaments> tournamentList = e.Result;
viewSource = new CollectionViewSource();
viewSource.Filter += TournamentWin_Filter;
viewSource.Source = tournamentList;
this.listBox1.ItemsSource = viewSource.View;
}
void TournamentWin_Filter(object sender, FilterEventArgs e)
{
if (e.Item != null)
e.Accepted = ((Tournaments)e.Item).Prev_Male_Winner.Contains(_selectedPlayerTournamentsWon);
}
private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (listBox1.SelectedItem != null)
{
Tournaments selectedTournament1 = listBox1.SelectedItem as Tournaments;
_SelectedItemTournament = (sender as ListBox).SelectedItem;
NavigationService.Navigate(new Uri("/Pages/TournamentDetailsPanorama.xaml", UriKind.Relative));
FrameworkElement root3 = Application.Current.RootVisual as FrameworkElement;
root3.DataContext = _SelectedItemTournament;
}
else
{
return;
}
}
On the listbox, set the IsSynchroziedWithCurrentItem to False. This fixed the issue.
I know this is a dirty solution, but you can set listBox1.SelectedIndex = -1
Related
I´m building a ContextMenu on the fly, like this
readinstance = null;
ContextMenu cMenu = new ContextMenu();
for (int i = 0; i < instances.Length; i++) {
string text = String.Format("{0} - {1}", instances[i].Id, instances[i].FormName);
MenuItem item = new MenuItem(text, new EventHandler(cMenuitem_Click));
item.Tag = instances[i];
cMenu.MenuItems.Add(item);
}
cMenu.Show((Button)sender, new Point(0, 0));
cMenu.Dispose();
if (readinstance == null)
throw new Exception("Must select some instance");
and the handler is
void cMenuitem_Click(object sender, EventArgs e)
{
MenuItem item = (MenuItem)sender;
readinstance = (FormPrintingStorage)item.Tag;
}
The menu displays correctly, but when I click some of the options, the handler is not called, so readinstance remains null, and the exception throws. As a side note, when I click any of the options, the menu disappears.
I cannot see what is wrong with my code. Any help will be appreciated.
I´m answering my own question, because I tried more ways.
The first one was to replace the ContextMenu with a ListView and an "Ok" button, at no luck, because the wait loop needed a Thread.Sleep. No comments.
The solution was to implement a new dialog with an empty list view an the Ok button. Some of the relevant code follows. Note that only TreeViewItem/s are moved between the main form and the dialog.
ListViewItem _result = null;
public ListViewItem Result { get { return _result; } }
public List<ListViewItem> Source
{
set
{
listView1.Items.Clear();
foreach (ListViewItem item in value)
listView1.Items.Add(item);
listView1.View = View.List;
}
}
private void button1_Click(object sender, EventArgs e)
{
if (_result == null)
return;
DialogResult = DialogResult.OK;
Close();
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
ListView list = (ListView)sender;
ListView.SelectedIndexCollection indices = list.SelectedIndices;
if (indices.Count == 0)
return;
_result = list.Items[indices[0]];
}
Getting the Result, the main form may do anything it wants with the Tag member. In fact, I´m using the same dialog for two different purposes in the same form.
I have a datagridview binded to a BindingList and inside this list I have comboboxes binded to a list which is a property of my BindingList, for understanding better:
ListA ---> binded to datagridview
ListA.ListB ---> binded to comboboxes
When I open the form I can corectly set my comboboxes showing the values inside the ListB, but when I add a new item I get an error (value is not valid), here is the code:
private void dataGridView_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
((DataGridViewComboBoxColumn)dataGridView.Columns["Names"]).DisplayIndex = 4;
for (int i = 0; i < People.Count; i++)
{
var cell = (DataGridViewComboBoxCell)dataGridView.Rows[i].Cells["Names"];
cell.DataSource = People[i].Names;
cell.Value = People[i].Names[0];
}
}
The code above works great, the problem happens here:
private void dataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
if (dataGridView.CurrentCell.ColumnIndex != dataGridView.Columns["Names"].Index)
return;
var cell = (DataGridViewComboBoxCell)dataGridViewICAO.CurrentCell;
if (cell.EditedFormattedValue.ToString().Equals(String.Empty)) return;
var regex = new Regex("[a-zA-Z]");
if (!regex.IsMatch(cell.EditedFormattedValue.ToString()))
e.Cancel = true;
else
{
People[cell.RowIndex].Names.Add(cell.EditedFormattedValue.ToString());
cell.Value = People[cell.RowIndex].Names.Last();
People[cell.RowIndex].Names = cell.Value.ToString();
}
}
on the row code cell.Value = People[cell.RowIndex].Names.Last(); I get the exception... Thanks to all!
This is how I set the combobox:
private void AddComboBox()
{
var comboNames = new DataGridViewComboBoxColumn { Name = "cmbNames", HeaderText = "Names" };
dataGridView.Columns.Add(comboNames);
}
private void dataGridView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (dataGridView.CurrentCell.ColumnIndex == dataGridView.Columns["cmbNames"].Index)
{
var combo = e.Control as ComboBox;
if (combo == null)
return;
combo.DropDownStyle = ComboBoxStyle.DropDown;
}
}
This code doesn't work. I don't know what to fix.
public sealed partial class Home : Page
{
public Home()
{
this.InitializeComponent();
ComboBox1.Items.Add("Hindiiiii");
}
string selection = null;
private void ComboBox1_SelectedIndex(object sender, EventArgs e)
{
if (ComboBox1.SelectedIndex!=1)
{
selection = ComboBox1.SelectedItem.ToString();
}
}
private void Continue(object sender, RoutedEventArgs e)
{
if(selection != null)
{
if (selection == "Hindiiiii")
this.Frame.Navigate(typeof(MainPage));
else if (selection == "English")
this.Frame.Navigate(typeof(Home));
}
}
When a user selects Hindiiiii on the main screen and clicks continues he is not redirected to the next page (MainPage).
Let's say your main page looks like this:
You can store the selection in a variable:
string selection = null;
private void ComboBox1_SelectedIndex(object sender, EventArgs e)
{
if (ComboBox1.SelectedIndex!=-1)
{
selection = ComboBox1.SelectedItem.ToString();
}
}
Then in your click event you can pass parameters between your pages:
private void Continue(object sender, RoutedEventArgs e)
{
if(selection != null)
this.Frame.Navigate(typeof(SomePage), selection); //send the contents of the variable to another page
}
And let's say you had another page with a TextBox and a TextBlock:
In your other pages' OnNavigatedTo event, you can retrieve the parameters so you don't have to create a page for every selected language:
string selection = null;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
selection = e.Parameter.ToString();
languageTextBlock.Text = selection; //the textblox is now the selected language
//decide what the contents are based on the selection
if (selection == "English")
translation.Text = "Something in English";
else if (selection == "Hindi")
translation.Text = "Something in Hindi";
else if (selection == "German")
translation.Text = "Something in German";
//etc
}
When you go to the next page, this allows you to create your page based on the selected item. This image demonstrates this:
Alternatively, you can solve your problem by creating a page for every possible language:
private void Continue(object sender, RoutedEventArgs e)
{
if(selection != null)
{
if(selection == "English")
this.Frame.Navigate(typeof(EnglishPage));
else if(selection == "Hindi")
this.Frame.Navigate(typeof(HindiPage));
//and so on
}
}
I prefer to do it this way because it's a lot simpler.
Edit: I see Items in the property box but I'm not aware of how to use it to add combo box items. This is the way that I usually see it done:
Of course you'll need to replace MainPage with your page (if it's not already named MainPage).
Another edit:
If you added the items via the properties panel, you have to access the Content. Use this instead, if you want:
string selection = null;
private void ComboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ComboBox1.SelectedIndex != -1)
{
//selection = ComboBox1.SelectedItem.ToString();
selection = (ComboBox1.SelectedItem as ComboBoxItem).Content.ToString();
}
}
I have a SelectionChanged event and works perfectly, but I want to figure out how to "catch" this selected item at the click of a button they need to pass it as parameter to another page and edit this Item. Here's the current code and button SelectionChanged I still implemented because this is what I need.
private void listCarros_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
ListBox listBox = sender as ListBox;
if (listBox != null && listBox.SelectedItem != null)
{
//pega o Carro que foi selecionado
Carro sCar = (Carro)listBox.SelectedItem;
btnEditCar.IsEnabled = true;
btnDeleteCar.IsEnabled = true;
}
else
{
btnEditCar.IsEnabled = false;
btnDeleteCar.IsEnabled = false;
}
}
I need to edit the selectedItem on this button:
private void btnEditCar_Click(object sender, EventArgs e)
{
//Here I need access to the selectedItem on SelectionChanged event.
}
If you could also tell me how to pass the object as parameter would be perfect.
You can do this with binding also
1.Bind ListBoxItem(Carro Object) to the tag of "btnEditCar" in xaml.
Xaml should be like this
<Button Name="btnEditCar" OnClick="btnEditCar_Click" Tag="{Binding}"/>
and now in
private void btnEditCar_Click(object sender, EventArgs e)
{
Carro sCar=(Carro)((sender as FrameworkElement).Tag)
}
This is the good practice,creating a class variable only for temporary purpose is hack
To give a better idea on my comments. Creating a class level variable is like this:
Notice that sCar is declared outside the method, but within the class.
Carro sCar = new Carro();
private void listCarros_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
ListBox listBox = sender as ListBox;
if (listBox != null && listBox.SelectedItem != null)
{
sCar = (Carro)listBox.SelectedItem;
...
private void btnEditCar_Click(object sender, EventArgs e)
{
sCar.ProperyYouWantToChange = "Stuff I want to change"
}
I had a old windows form WebBrowser and I had:
public WebBrowser getCurrentWebBrowser()
{
return (WebBrowser)TabControl.SelectedTab.Controls[0];
}
I want to know how to do the same thing in WPF.
Thanks for any help.
You can hook the TabContols' SelectionChanged event and then have code like this in the callback...
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
HeaderedContentControl hcc = e.AddedItems[0] as HeaderedContentControl;
if (hcc != null)
{
WebBrowser webBrowser = hcc.Content as WebBrowser;
if (webBrowser != null)
{
// do something...
}
}
}
If you have a WebBrowser in more than one tab, you can name the TabItems and adapt your callback thusly...
<TabItem Header="Browser" Name="MyBrowserTabItem">
<WebBrowser/>
</TabItem>
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
HeaderedContentControl hcc = e.AddedItems[0] as HeaderedContentControl;
if (hcc != null && hcc.Name == "MyBrowserTabItem")
{
WebBrowser webBrowser = hcc.Content as WebBrowser;
if (webBrowser != null)
{
// do something...
}
}
}
The 'AddedItems' property of the SelectionChangedEventArgs is a list of objects that have been selected since the last time the event was fired. For a TabControl, AddedItems should normally have a length of 1, and the single element should be an instance of HeaderedContentControl (i.e., the TabItem).