I am trying to get text from WPF ComboBox, when it will select but unable to get any text. Below are the codes which I have tried. If someone please help me to get text from ComboBox when I select different Content. please note that, ComboBox will load data from sql server which is working perfectly !
my XAML code is:
<ComboBox x:Name="comboID" TabIndex="27" SelectedValuePath="Content" SelectionChanged="comboID_SelectionChanged" HorizontalAlignment="Left" Margin="694,396,0,0" VerticalAlignment="Top" Width="165"/>
below are my C# codes example which I have tried:
string str1 = comboID.SelectedItem.ToString();
string str2 = comboID.SelectedValue.ToString();
string str3 = comboID.Text;
ComboBoxItem cmb = comboID.SelectedItem as ComboBoxItem;
var myVal = sender as ComboBox;
string value = comboID.SelectedItem as string;
Use this code instead of yours for adding items in combobox:
SqlConnection conn = new SqlConnection("your connection");
SqlCommand cmnd = new SqlCommand();
SqlDataReader sdr = null;
conn.Open();
cmnd.Connection = conn;
String query = "Select ID from Seller ORDER BY ID";
cmnd.CommandText = query;
sdr = cmnd.ExecuteReader();
while (sdr.Read())
{
comboID.Items.Add(sdr.GetString(0));
}
Now you can use:
string str = comboExporterID.SelectedItem.ToString();
I have created a simple code to give you a rough idea.
My Xaml
<Window x:Class="StackOverflow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="350">
<StackPanel Orientation="Horizontal">
<Label Content="Select Item" x:Name="LblSelectNumber" MinWidth="50px" Margin="5"></Label>
<ComboBox x:Name="ComboId" DisplayMemberPath="Number"
SelectedValuePath="Content" SelectionChanged="ComboID_OnSelectionChanged" MinWidth="100"
HorizontalAlignment="Left" Margin="5" VerticalAlignment="Top" />
</StackPanel>
</Window>
My code behind
public partial class MainWindow : Window
{
private readonly List<MyItem> _items;
public MainWindow()
{
InitializeComponent();
_items = new List<MyItem>
{
new MyItem{Content = "Test1",Number = "One"},
new MyItem{Content = "Test2",Number = "Two"},
new MyItem{Content = "Test3",Number = "Three"}
};
ComboId.ItemsSource = _items;
}
private void ComboID_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
MessageBox.Show(ComboId.SelectedValue.ToString());
}
}
public class MyItem
{
public string Content { get; set; }
public string Number { get; set; }
}
Please observe the usage of DisplayMemberPath property in ComboBox
A simple suggestion. Please use MVVM pattern while creating your application as it will help you to maintain the solution in the long run. What ever I have done above can be achieved quite easily using MVVM pattern
Simple code. Try this, should work
string s = comboID.text;
Add the Tag property to the comboboxitems:
<Comboboxitem Tag="This Value"/>
Then
GetValue=ComboBoxName.SelectedItem.Tag.ToString()
GetValue will be "This Value" instead of the System.windows.combobox blah blah blah..
Related
This is the first time I try to bind combobox. I'm trying get values from my database. However, with the code below, I'm getting this as a result (the same number of results as the rows count of my table):
GUITest.DB.Structure
where GUITest -> namespace of my project, DB -> folder where structure.cs is.
private ObservableCollection<Structure> _lists;
public ObservableCollection<Structure> Lists
{
get { return _lists; }
set
{
_lists = value;
NotifyOfPropertyChange("Lists");
}
}
public ObservableCollection<Structure> GetStructures()
{
ObservableCollection<Structure> products = new ObservableCollection<Structure>();
using (SqlConnection conn =
new SqlConnection(ConfigurationManager.ConnectionStrings["StringConnexion"].ConnectionString))
{
conn.Open();
SqlCommand cmdNotes =
new SqlCommand("SELECT * FROM Structure", conn);
using (SqlDataReader reader = cmdNotes.ExecuteReader())
{
var ordinals = new
{
CodeStr = reader.GetOrdinal("CODE_STR"),
NomStr = reader.GetOrdinal("NOM_STR"),
};
while (reader.Read())
{
var temp = new TableStructure();
temp.CodeStr = reader.GetString(ordinals.CodeStr);
temp.NomStr = reader.GetString(ordinals.NomStr);
products.Add(temp.SqlProduct2Product());
}
}
}
return products;
}
public CreateAccountViewModel()
{
_lists = new ObservableCollection<Structure>();
Lists = GetStructures();
}
XAML:
<ComboBox SelectedItem="{Binding Path=NomStr}" ItemsSource="{Binding Lists}"></ComboBox>
As noted in the comments, you want DisplayMemberPath not SelectedItem
DisplayMemberPath says "Display this property (as a path) as the ItemTemplate" it is functionally equivalent (though not code equivalent) to, for a path of X:
<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=X}"/>
</DataTemplate>
</ComboBox.ItemTemplate
</ComboBox>
This is why you don't have the Binding extension in it, the framework puts it in for you.
SelectedItem is just that, the current selection of the combo box. It doesn't affect the display in any way.
I need to bind the ListBoxItem and DataGrid in the following way:
A user doubleclicks on the ListBoxItem and the sql query is performed and the retrieved data is shown on the DataGrid.
Here's what I have:
<DataGrid x:Name="GridStatistics" Margin="0,144,0,0" />
<ListBox x:Name="LstStat" HorizontalAlignment="Left" Height="129" Margin="10,10,0,0"
VerticalAlignment="Top" Width="330" FontSize="16"
ItemsSource="{Binding StatisticsQueries}" Cursor="Arrow" PreviewMouseRightButtonDown="LstStat_PreviewMouseRightButtonDown" PreviewMouseRightButtonUp="LstStat_PreviewMouseRightButtonUp" MouseDoubleClick="LstStat_MouseDoubleClick">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Path=Name}" FontWeight="Medium" FontSize="18" FontFamily="HelveticaNeueCyr"/>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Show" Click="MenuItem_OnClick" />
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
And my c# code:
public ObservableCollection<Query> StatisticsQueries {get{...}}
private void LstStat_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (LstStat.SelectedIndex < 0) return;
var item = LstStat.SelectedItem as Query;
using (var connection = new MySqlConnection(DatabaseModel.ConnectionString))
{
connection.Open();
if (item != null)
using (var cmd = new MySqlCommand(item.Text, connection))
{
var dt = new DataTable();
var adapter = new MySqlDataAdapter(cmd);
adapter.Fill(dt);
GridStatistics.DataContext = dt;
}
connection.Close();
}
e.Handled = true;
}
And the class Query public class Query : INotifyPropertyChanged has all the properties that are used in the code, so no mistakes there.
Although the data is retrieved correctly, the DataGrid doesn't react at all. Maybe there are some mistakes in binding or setting DataContext.
Could you please help me to correctly bind the ListBoxItem DoubleMouseClick and DataGrid DataContext? Should I create a separate class for that?
Try it :
using (var cmd = new MySqlCommand(item.Text, connection))
{
.
.
GridStatistics.ItemsSource = dt.DefaultView;
}
Solved the issue doing this:
1) Adding this:
public DataTable StatisticsDataTable { get; private set; }
2) Then changing my method part here:
StatisticsDataTable = dt;
GridStatistics.DataContext = StatisticsDataTable;
3) The XAML binding became the following:
ItemsSource="{Binding}"
Thanks everyone who tried to help!
I initially add some string objects in a listBox and afterwards I want to set the Item that is selected:
List <string> CustName = new List<string>();
....///add items to CustName///...
listBox1.ItemsSource = CustName;
string selection = "myselection" ///this string is contained in CustName
listBox1.SelectedValue = selection;
However tha above doesn't work seens the selected Item is the first item of the listBox and not the one I try to set...
why not use binding, something like this.
XAML:
<ListBox ItemsSource={Binding CustName} SelectedItem={Binding MySelectedItem} />
then have a property
private string mySelectedItem;
public string MySelectedItem
{
get{return mySelectedItem;}
set
{
mySelectedItem=value;
RaisePropertyChanged("MySelectedItem");
}
if you want to set the SelectedItem manually in code, then just do MySelectedItem=yourItem;
Don't forget to set DataSource of the listbox and implement INotifyPropertChanged
XAML:
<Grid>
<ListBox HorizontalAlignment="Left" Name="listBox1" Height="100" Margin="310,172,0,0" VerticalAlignment="Top" Width="100"/>
</Grid>
CodeBehind.cs
public MainWindow()
{
InitializeComponent();
List<string> CustName = new List<string>();
CustName.Add("test1");
CustName.Add("test2");
CustName.Add("myselection");
listBox1.ItemsSource = CustName;
string selection = "myselection";
listBox1.SelectedItem = selection;
}
I have this block of code as you can see in the screen print correctly loads the data you want and store the list of objects PopularVideos:
item { Title = Hey Porsche, Url = http://www.unnu.com/wp-content/plugins/wordpress-popular-posts/timthumb.php?src=http://www.unnu.com/wp-content/uploads/2013/03/019.jpg&h=65&w=275 } <>f__AnonymousType0<string,string>
item.Title "Hey Porsche" string
item.Url "http://www.unnu.com/wp-content/plugins/wordpress-popular-posts/timthumb.php?src=http://www.unnu.com/wp-content/uploads/2013/03/019.jpg&h=65&w=275" string
Need to load these objects in my list box with binding or has otherwise also can be. But the windows phone does not work with DataSource and DisplayMember.
My XAML:
<ListBox Name="listBoxPopular">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Name="imagem" Source="{Binding Path=Url}"/>
<TextBlock Text="{Binding Titulo}" Tap="HyperlinkButton_Tap" FontSize="30" Foreground="#FF159DDE" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</controls:PanoramaItem>
My Class is:
class PopularVideos
{
public PopularVideos() { }
public PopularVideos(string titulo, string url)
{
Titulo = titulo;
BitmapImage Img = new BitmapImage(new Uri(url));
}
public string Titulo { get; set; }
public Uri Url { get; set; }
}
and my codebehind is:
_popVideos = new List<PopularVideos>();
var data = e.Document.DocumentNode.SelectSingleNode("//div[#class='content']")
.Descendants("img")
.Select(img => new
{
Title = img.Attributes["alt"].Value,
Url = img.Attributes["src"].Value,
}).ToList();
foreach (var item in data)
{
PopularVideos pop = new PopularVideos(item.Title, item.Url);
_popVideos.Add(new PopularVideos(item.Title, item.Url));
}
listBoxPopular.ItemsSource = _popVideos;
This code works because they are carrying the images and links in the objects, just can not bring up in my list box.
Have a bindable ObservableCollection<Item> (preferrably in a ViewModel).
Use the ListBox.ItemsSource property to bind to said ObservableCollection<Item>. The standard binding rules apply.
Each of the items in ListBox will be a representation of the items in the core collection that is bound to the control, so bind to its properties the same way you would to anything else.
It's reply to comment:
Ok, please read once again the article that #Den send to you. And please remove DataContext Property from ListBox, add x:Name="myList" to ListBox and in code-behind: myList.DataContext = this; This is not the best solution, but it's easy to understand and firstly you need to understand it :) Best regards.
I've posted a similar problem here and wasn't able to successfully implement the solution suggested to me as it wasn't working.I've found a way round and wanted to improve it by binding the combobox to a custom objects to enable data validation.here is the xaml for this one
<Window xmlns:data="clr-namespace:Myproject">
<Window.Resources>
<data:UserLogin x:Key="user"></data:UserLogin>
<DataTemplate x:Key="comboTemplate">
<TextBlock Text="{Binding Path=username}" />
</DataTemplate>
</Window.Resources>
<ComboBox Margin="18,121,24,0" Name="cmbEmail" Tag="email" TabIndex="1" ToolTip="enter the email you signed up with here" IsEditable="True" IsSynchronizedWithCurrentItem="True" ItemTemplate="{StaticResource comboTemplate}" ItemsSource="{Binding}" Height="23" VerticalAlignment="Top" Style="{DynamicResource cmbBoxerrors}">
<ComboBox.Text>
<Binding Path="Loginname" Source="{StaticResource user}" ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<ExceptionValidationRule/>
</Binding.ValidationRules>
</Binding>
</ComboBox.Text>
</ComboBox>
</Window>
and the xaml.cs is
if (con != null)
{
if (con.State == ConnectionState.Closed)
con.Open();
SqlCeCommand cmdusers = new SqlCeCommand("select * from users order by id", con);
SqlCeDataAdapter da = new SqlCeDataAdapter(cmdusers);
userdt = new DataTable("users");
da.Fill(userdt);
cmbEmail.DataContext = userdt;
}
and the UserLogin Class is
class UserLogin :IDataErrorInfo
{
private string _loginname = "";
private string _password;
public string this[string columnName]
{
get
{
string result = null;
if(columnName == "Loginname")
{
if(string.IsNullOrEmpty(this._loginname))
{
result = "Login Name cannot be Empty";
}
}
if (columnName == "Loginname")
{
if(!Util.ValidateRegexPatern(Properties.Resources.emailRegex,this._loginname))
{
result = "MalFormed Email address. Please write a correct email addess";
}
}
return result;
}
}
public string Error
{
get { return null; }
}
public string Password
{
get { return _password; }
set { _password = value; }
}
public string Loginname
{
get { return _loginname; }
set { _loginname = value; }
}
}
the problem is when i use ItemTemplate the selected item shows System.Data.DataRowView but dropdown list items show correctly and when i swap the ItemTemplate with DisplayMemberPath it's the opposite behavior as in selected items is correct and dropdown list items show System.Data.DataRowView.using them both throws an exception as i can't use them both selected and dropdown list items show correctly.
I don't really know what i'm not doing correctly.Can anyone shed some light on this i'll be verry thankfull.Thanks for reading this
It goes like this: you set the data context of the ComboBox to an instance of type DataTable. Then you set the ItemsSource to {Binding} which means each item in the ComboBox will bind to a DataRow (which doesn't have either loginname, nor username as properties). And here the binding stops working. There's no implicit way to convert from a DataRow to a UserLogin.
You ca either implement a converter to do the conversion or convert the rows to UserLogin one by one and set the DataContext of the ComboBox to the list of UserLogin (or an ObservableCollection if you need more advanced functionality).
In either case drop the <ComboBox.Text> ... </ComboBox.Text> part.
Hope this helps you...