I have a ListBox of Dockpanels which display "FieldName:, [_____] (user input textbox)". After the user populates the field, I'm looking for a LINQ way to take the pairs and throw them into a KeyValuePair object.
<DataTemplate x:Key="ExtraLoginInfoTemplate">
<DockPanel>
<TextBlock Name="CodeID" Text="{Binding Path=ID,Converter={BLL:CodeMarkupExtension}}" />
<TextBox Name="Input"/>
</DockPanel>
</DataTemplate>
<ListBox Name="extraLoginInfoListBox" ItemsSource="{Binding}" ItemTemplate="{StaticResource ExtraLoginInfoTemplate}"/>
//codebehind
extraLoginInfoListBox.DataContext = cvList; //list of codevalue objects
private void submitButton_click(object sender, RoutedEventArgs e)
{
KeyValuePair<string,string> myInputs = /* ? some linq query to get the data from extraLoginInfoListBox */
}
You need a property to be bound with your Input textbox to store whatever value was entered by user:
<TextBox Name="Input" Text="{Binding Path=IDValue, Mode=TwoWay}" />
And then, you can use following code:
var keyValuePairs = cvList.ToDictionary((obj) => obj.ID, (obj) => obj.IDValue);
Related
I am building an app that will return data from database based on the items that are checked on check box. I have successfully displayed data from database by binding the data. Like this:
XAML:
<ListBox x:Name="listBox1" ItemsSource="{Binding}" HorizontalAlignment="Left" Height="52" Margin="141,264,0,0" VerticalAlignment="Top" Width="307" SelectionMode="Multiple">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox x:Name="checkBox1" IsChecked="{Binding IsSelected}" Content="{Binding NacinGrejanja}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
C#:
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
Dataset1 ds= new Dataset1 ();
GrejanjeTableAdapter gta = new GrejanjeTableAdapter();
gta.Fill(ds.Grejanje);
listbox1.DataContext = ds.Grejanje;
}
But I am unable to figure out how to extract string values from checked values and then again search for those values in database. I can't access any of the properties for checkBox1 through code.
Also I would want first to check if any of the checkbox items is checked in the first place.
You can use following linq:
ds.Grejanje.Where(item => item.IsSelected == true);
It will return the list of items which are checked.
I have a listBox1 in which data are binding from the list. Then I want to when I select any item from listBox1 in listBox2 will binding data from another list.
private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Teams teams = (Teams)listBox1.SelectedItems[0];
getH2hResults("//td[#class='hell']", teams.Team1, teams.Team2); // add elements to list
getH2hResults("//td[#class='dunkel']", teams.Team1, teams.Team2); // and here also
listBox2.ItemsSource = lists.h2hList;
}
On the first time this work, but for the twice time listBox2 doesn't displays new data.
public class Lists : BindableBase
{
public Lists()
{
_teamsList = new List<Teams>();
_h2hList = new List<H2H>();
}
private List<Teams> _teamsList;
public List<Teams> teamsList
{
get
{
return _teamsList;
}
set
{
if (value != _teamsList)
{
_teamsList = value;
RaisePropertyChanged("teamsList");
}
}
}
private List<H2H> _h2hList;
public List<H2H> h2hList
{
get
{
return _h2hList;
}
set
{
if (value != _h2hList)
{
_h2hList = value;
RaisePropertyChanged("h2hList");
}
}
}
}
And XAML
<ListBox Name="listBox1" Width="300" Height="300"
VerticalAlignment="Top"
HorizontalAlignment="Left"
ItemsSource="{Binding teamsList}" SelectionChanged="listBox1_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Foreground="#FF4273CD" Text="{Binding Team1, Mode=TwoWay}"></TextBlock>
<TextBlock Text=" vs " FontWeight="Bold"></TextBlock>
<TextBlock Foreground="#FF4273CD" Text="{Binding Team2, Mode=TwoWay}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox Name="listBox2" Grid.Column="1" Width="300" Height="300"
VerticalAlignment="Top"
HorizontalAlignment="Left"
ItemsSource="{Binding h2hList}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding date, Mode=TwoWay}"></TextBlock>
<TextBlock Text="{Binding result, Mode=TwoWay}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
RaisePropertyChanged("teamList");
is Wrong your propery is named 'teamsList' with an S,
change to:
RaisePropertyChanged("teamsList");
It is the public property you bind to and notify changes of,
edit:
also change your binding:
ItemsSource="{Binding teamList}"
to
ItemsSource="{Binding teamsList}"
Edit 2:
listBox2.DataContext = xxx
Not itemsource = xxx
With the line (in listBox1_SelectionChanged)
listBox2.ItemsSource = lists.h2hList;
you are effectively removing the binding from the ItemsSource property of listBox2.
Instead, you should only update the h2hList property in your Lists class (which presumably happens in getH2hResults) and remove the above line from your code.
Note however that it is not sufficient to clear and re-fill that list. You need to set the h2hList property in order to get a property change notification raised:
var newList = new List<H2H>();
// fill newList before assigning to h2hList property
lists.h2hList = newList;
If you want to keep the list and just change its elements, you would need to use ObservableCollection<H2H> instead of List<H2H> as collection type. This would be the better approach anyway, as you would not have to care for when exactly you add elements to a newly created collection.
i have a listbox which has a data template binded to task from xml file,i want to delete selected template on button click,but its throws me an exception "Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead."
here is the code for xaml
<TabItem>
<Canvas Height="700" Width="850">
<Canvas.Resources>
<XmlDataProvider x:Key="Tasks" XPath="tasks"
Source="http://store.tymesheet.com/templates/Graphic-Designer.xml"/>
<DataTemplate x:Key="tasktemplate1">
<Canvas Height="50" Width="850" >
<Label Content="{Binding XPath=name}" Height="30"
Width="170" Canvas.Top="10" Canvas.Left="150"
Background="LightGray"/>
<TextBox Height="30" Width="120" Canvas.Top="10"
Canvas.Left="370" Background="AliceBlue"/>
<Label Canvas.Left="500" Canvas.Top="10">$</Label>
<Button Tag="{Binding}" Click="deletebuttonclick"
Canvas.Top="12" Height="10" Width="30"
Canvas.Left="600"/>
</Canvas>
</DataTemplate>
</Canvas.Resources>
<ListBox ItemTemplate="{StaticResource tasktemplate1}"
ItemsSource="{Binding Path=ChildNodes, Source={StaticResource Tasks}}"
x:Name="tasklistbox" Height="700" Width="850"/>
<Label Canvas.Top="-18" Canvas.Left="185">Select Task</Label>
<Label Canvas.Top="-18" Canvas.Left="377" RenderTransformOrigin="0.58,0.462">Enter Bill Rates</Label>
<Button Canvas.Left="39" Canvas.Top="575" Width="139">Click to add the task</Button>
</Canvas>
</TabItem>
here is the code behind for delete button
private void deletebuttonclick(object sender,RoutedEventArgs e)
{
tasklistbox.Items.Remove(tasklistbox.SelectedItem);
}
where am i wrong?,help.thanx.
The error that you displayed is fairly self explanatory:
Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead.
Clearly, as you should know, you used the ItemsSource property on the ListBox:
<ListBox ItemTemplate="{StaticResource tasktemplate1}"
ItemsSource="{Binding Path=ChildNodes, Source={StaticResource Tasks}}"
x:Name="tasklistbox" Height="700" Width="850" />
The error is telling you to Access and modify elements with ItemsControl.ItemsSource instead. So instead of not doing what it says:
private void deletebuttonclick(object sender,RoutedEventArgs e)
{
tasklistbox.Items.Remove(tasklistbox.SelectedItem);
}
Try actually doing what it says:
private void deletebuttonclick(object sender,RoutedEventArgs e)
{
tasklistbox.ItemsSource = null;
}
Or even better:
private void deletebuttonclick(object sender,RoutedEventArgs e)
{
ChildNodes = null;
}
UPDATE >>>
So it seems that we have another new user that asks one thing and when given that thing asks for another thing without so much as a 'thank you'... shame... a real shame.
First you need to data bind to the ListBox.SelectedItem property so that you know which item is selected:
<ListBox ItemTemplate="{StaticResource tasktemplate1}" SelectedItem="{Binding Item}"
ItemsSource="{Binding Path=ChildNodes, Source={StaticResource Tasks}}"
x:Name="tasklistbox" Height="700" Width="850" />
This Item property should be of the same type as the items in the ChildNodes collection... if it's not clear enough - you need to add that property next to your collection property. Then to remove that item in your handler, you just need to do this:
private void deletebuttonclick(object sender,RoutedEventArgs e)
{
ChildNodes.Remove(Item);
}
If you want to remove the item, then I would suggest to create ObservableCollection of XmlNode and bind ItemsSource with that. I suggested to use ObservableCollection because it implements INotifyCollectionChanged so whenever list is updated target which in your case is ListBox will automatically be updated.
In code behind
(Add System.Collections.ObjectModel namespace to use ObservableCollection<T>)
public MainWindow()
{
InitializeComponent();
XmlDocument doc = new XmlDocument();
doc.Load("http://store.tymesheet.com/templates/Software-Developer.xml");
var taskList = doc.ChildNodes.OfType<XmlNode>()
.Where(node => node.Name == "tasks")
.SelectMany(node => node.ChildNodes.OfType<XmlNode>());
Tasks = new ObservableCollection<XmlNode>(taskList);
this.DataContext = this;
}
public ObservableCollection<XmlNode> Tasks { get; set; }
private void deletebuttonclick(object sender, RoutedEventArgs e)
{
XmlNode selectedNode = ((Button)sender).DataContext as XmlNode;
Tasks.Remove(selectedNode);
}
Of course you need to update XAML as well:
<ListBox ItemsSource="{Binding Tasks}"
ItemTemplate="{StaticResource tasktemplate1}"
x:Name="listBox" Height="700" Width="850"/>
I've got for example ListBox with two TextBlocks like this:
<ListBox Name="listboxNews"
SelectionChanged="listboxNews_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Width="400"
Height="70">
<TextBlock Text="{Binding Title}" name="title" />
<TextBlock Text="{Binding Description}" name="desc" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And as you can see, I've got listboxNews_SelectionChanged method, in which i need to select Text of first TextBlock (if posibble by name so it will be independent on order of textblocks), but this one, which I select. For example if first item has title "Item 1" and second "Item 2" and I click on second one, i need to get "Item 2". I was trying something with listboxNews.Items, but i guess this is not correct. Thanks for help.
The SelectedItem property will hold the currently selected object. You can just cast that and take the Title property.
Try this code:
private void listboxNews_SelectionChanged(object sender, SelectionChangedEventArgs e) {
var current = listboxNews.SelectedItem as MyObjectType;
MessageBox.Show(current.Title);
}
Change MyObjectType with the type of your object.
This is a copy and paste out of a working Windows Phone 8 solution.
This was also tested successfully in WPF.
private void ListBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
foreach (UIElement item in (sender as ListBox).Items)
{
if ((sender as ListBox).SelectedItem == item)
{
foreach (UIElement InnerItem in (item as StackPanel).Children)
{
if ((InnerItem is TextBlock) && (InnerItem as TextBlock).Name.Equals("title"))
{
MessageBox.Show((InnerItem as TextBlock).Text);
}
}
}
}
}
I'm using a ListBox to display all values contained in Dictionary<> object:
<ListBox Height="519" x:Name="ContactsListBox" Width="460" Margin="0,0,0,0" SelectionChanged="ContactsListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Key}" Margin="5" Foreground="{StaticResource PhoneAccentBrush}"/>
<TextBlock x:Name ="LastNameData" Text="{Binding Value}" Margin="20, 0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Content is filled by the following code:
Dictionary<long, Contact> contacts = new Dictionary<long, Contact>();
this.ContactsListBox.ItemsSource = contacts;
Now, I would like to 'know' which specific "Contact" in ListBox is currently selected, either by knowing its Key, or just by extracting value from "LastNameData" TextBlock.
I tried doing something like that, but obviosly it doesn't work:
private void ContactsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox lb = this.ContactsListBox.SelectedItem as ListBox;
this.Test_SomeOtherTextBlock.Text = lb.ToString();
}
I would really appreciate your help!
you can even do the follwing:
<ListBox Height="519" x:Name="ContactsListBox" Width="460" Margin="0,0,0,0" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Key}" Margin="5"/>
<TextBlock x:Name ="LastNameData" Text="{Binding Value}" Margin="20, 0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Grid DataContext="{Binding ElementName=ContactsListBox, Path=SelectedItem}" Margin="0,470,0,0">
<TextBlock Text="{Binding Value}"/>
</Grid>
So you don't need code behind...
BR,
TJ
There are several problems:
In Xaml you probably don't want to display the class name, but a reasonable string, for example:
<TextBlock x:Name ="LastNameData" Text="{Binding Value.LastName}" Margin="20, 0" />
In the selection processing the selected item is KeyValuePair<...>. You could easily find it yourself, if you looked at the returned type in debugger. (Should be kind of a reflex for a programmer, hence a questions like above should never appear :))
private void ContactsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
KeyValuePair<long, Contact> kv = (KeyValuePair<long, Contact>)this.ContactsListBox.SelectedItem;
Contact c = (Contact)kv.Value;
Debug.WriteLine(c.LastName);
}
Your code is good, using ListBox.SelectedItem is the right approach.
I think the problem is that you should cast it as ListBoxItem, not ListBox. And also to get to its value using DataContext, so something like along these lines (not tested, I'm not sure about accessing DataContext value in the last line):
private void ContactsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBoxItem lbi = this.ContactsListBox.SelectedItem as ListBoxItem;
var dataContext = lbi.DataContext;
this.Test_SomeOtherTextBlock.Text = dataContext.Value.ToString();
}
Try this it works for me, will help you to...
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox ContactListBox = sender as ListBox;
ListBoxItem listBoxItem = ContactListBox .ItemContainerGenerator.ContainerFromItem(ContactListBox.SelectedItem) as ListBoxItem;
if (listBoxItem == null)
{
return;
}
TextBlock txtBlock = FindVisualChildByName(listBoxItem, "ListTextBlock");
MessageBox.Show(txtBlock.Text);
}
private static T FindVisualChildByName<T>(DependencyObject parent, string name) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
string controlName = child.GetValue(NameProperty) as string;
if (controlName == name)
{
return child as T;
}
T result = FindVisualChildByName<T>(child, name);
if (result != null)
return result;
}
return null;
}
private void ContactsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox lb = this.ContactsListBox.SelectedItem as ListBox;
this.Test_SomeOtherTextBlock.Text = lb.ToString();
}
will go something like this..
private void ContactsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox lb = this.ContactsListBox.SelectedItem as ListBox;
DataTemplate template=lb.ContentTemplate;
//Now here you have to extract the content of the data template
and then you need to extract the TextBlock from that content.
}
This is just an overview of the functionality.Sorry not able to post complete code.