How to Identify button for list item - wpf

How do i access the object UserNames, that is bound to the list??
What i did so far:
Item of the list is object in my case:
new List<UserNames>();
this.users.Add(new UserNames() {Id = 1, UserName = "name 1"});
I am using data template for which i have label and button.
My List is as follows:
<ListBox Grid.Column="1" Grid.Row="1" Name="listBox1" ItemsSource="{Binding}" SelectedValuePath="Id">
<ListBox.ItemTemplate>
<DataTemplate>
<WrapPanel Orientation="Vertical">
<StackPanel>
<Label Content="{Binding UserName}" />
</StackPanel>
<StackPanel Name="ButtonStackPanel">
<Button Name="MyButton" Content="Click Me" Click="MyButton_Click">
</Button>
</StackPanel>
</WrapPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Where my method for Button is. As you can see i did try to utilise the parent option, but without sucess
private void MyButton_Click(object sender, RoutedEventArgs e)
{
//StackPanel panel = (StackPanel)((Button)sender).Parent;
//WrapPanel wrapPanel = (WrapPanel) panel.Parent;
//ListItem listItem = (ListItem) wrapPanel.Parent;
//ListBox box = (ListBox) listItem.Parent;
//UserNames itemToReport = (UserNames) (box.SelectedItem);
//MessageBox.Show(itemToReport.UserName);
}

You can use the Button's DataContext, since it will be your UserName object
private void MyButton_Click(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
UserNames data = b.DataContext as UserNames;
MessageBox.Show(data.UserName);
}
I've always thought that with WPF, your application is the DataContext, while the UI objects like Buttons, ListBoxes, TextBoxes, etc are simply a pretty layer that sits on top of the DataContext to allow the User to interact with it.

In the XAML, set the Tag property to the current item.
In the click handler, cast it back.
Usernames user = (sender as Button).Tag as Usernames;

To bind a datacollection it is often easiest to use an ObservableCollection (if the data is changing runtime). When you do the binding you have to define a datacontext, a datasoure and a datapath. I will advice you to read some more about binding on MSDN :D

This will work for you -
MessageBox.Show(((sender as Button).DataContext as UserNames).UserName);

Related

Custom ListBox selection in WPF

I have a Custom ListBox with multiple columns per one Item
<ListBox Name="UserListBox" Loaded="GetUsers_OnLoad" SelectionChanged="UserSelected">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel Name="UserDockPanel" Margin="4">
<TextBlock Name="UsernameTextBlock" Text="{Binding Path=Username}"/>
<CheckBox Name="OneCheckBox" IsHitTestVisible="False" IsChecked="{Binding One}" />
<CheckBox Name="TwoCheckBox" IsHitTestVisible="False" IsChecked="{Binding Two}" />
<CheckBox Name="ThreeCheckBox" IsHitTestVisible="False" IsChecked="{Binding Three}" />
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
What I am trying to do is when the user selects an item that I can parse the individual values for that item (UsernameTextBlock, OneCheckbox, TwoCheckBox, ThreeCheckBox).
I have tried selected which throws an error and selection changed seems to work but I do not know how to retrieve the individual values for the item selected.
Any insight would be appreciated.
UPDATE:
Here is the code behind
private void UserSelected(object sender, RoutedEventArgs e)
{
var userListBox = FindName("UserListBox") as ListBox;
var selectedItem = userListBox.SelectedItem as ListBoxItem;
MessageBox.Show(selectedItem.Username);
}
I am currently just showing a message popup to show what I am accessing
UPDATE 2:
private void GetUsers_OnLoad(object sender, RoutedEventArgs e)
{
_outreachAuths = _outreachTableAdapter.GetOutreachAuths();
var users = new List<UserItem>();
foreach (DataRow row in _outreachAuths.Rows)
{
users.Add(new UserItem() { Username = row.ItemArray[0].ToString(), One = false, Two = true, Three = ((row.ItemArray[2].ToString() == "1"))});
}
var userList = sender as ListBox;
if (userList != null) userList.ItemsSource = users;
}
In your UserSelected handler you're casting the selected item to type ListBoxItem:
var selectedItem = userListBox.SelectedItem as ListBoxItem;
In order to access the properties you're looking for you'll need to cast it to its original type which is, I believe, UserItem.
var selectedItem = userListBox.SelectedItem as UserItem;
Bind the listbox's SelectedItem property to a property in your view model. You will then have access to the item when it's value changes in the VM.
<ListBox Name="UserListBox" Loaded="GetUsers_OnLoad" SelectionChanged="UserSelected" SelectedItem={Binding Path=PropertyOnViewModel}>

TextBlock MouseDown URL - How get my url in my code behind?

I ve a list from sharepoint and i collect from this list an hyperlink.
As i want my textbox to be like an hyperlink I ve added an event on mousedown to open this hyperlink, My concern is how to collect this hyperlink in the codebehind with the sender.
For the moment I've just hide this hyperlink in the tooltip maybe i can manage this differently any suggestion will be grantly appreciated.
My point so far, i don't know how to get this tooltip in the code behind.
Thanks
My XAML Code :
<ListBox Name="ListboxTips" ItemsSource="{Binding}" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=Picture}" Height="20"></Image>
<TextBlock MouseDown="TextBlock_MouseDown_URL" TextDecorations="Underline"
Margin="10,10,20,10" Width="160" TextWrapping="Wrap"
Text="{Binding Path=TitleTip}"
ToolTip="{Binding Path=URL}"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My code behind :
foreach (SPSClient.ListItem item in TipsList)
{
var tips = new Tips();
tips.TitleTip = item.FieldValues.Values.ElementAt(1).ToString();
tips.App = item.FieldValues.Values.ElementAt(4).ToString();
// get the Hyperlink field URL value
tips.URL = ((FieldUrlValue)(item["LinkDoc"])).Url.ToString();
//should collect the description of the url
//tips.URLdesc = ((FieldUrlValue)(item["LinkDoc"])).Description.ToString();
tips.Picture = item.FieldValues.Values.ElementAt(4).ToString();
colTips.Add(tips);
}
ListboxTips.DataContext = colTips;
....
private void TextBlock_MouseDown_URL(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//string test = (ToolTip)(sender as Control).ToString();
System.Diagnostics.Process.Start("http://www.link.com");
//System.Diagnostics.Process.Start(test);
}
Thanks a lot,
You can just access the property directly. It is not elegant, but will work!
private void TextBlock_MouseDown_URL(object sender, MouseButtonEventArgs e)
{
TextBlock txtBlock = sender as TexBlock;
// just access the property
string url = txtBlock.ToolTip as string;
}
A more elegant approach might be to use a Button, Hyperlink or something that exposes a Command, so that you can bind the 'click' action to a command on your view model that performs the action you wish to execute.
usually you stick any data you want to trespass somewhere to Tag attribute.
<TextBlock .. Tag="{Binding Path=URL}" />
This is easily retrievable as a public property:
private void TextBlock_MouseDown_URL(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var tb = sender as TextBlock;
if(tb != null)
{
var neededUrl = tb.Tag;
}
}

How to select all checkbox inside telerik combox on checbox Checked event?

I have on checkbox inside telerik combo control. If User click on "All" option from checkbox list then I want select all checkboxs.
checkbox values.
My Sample code is below.
<telerik:RadComboBox Name="rcbDays" Grid.Row="1" Grid.Column="1" Width="200" HorizontalAlignment="Left" ItemsSource="{Binding MonthDaysList}" VerticalAlignment="Center" >
<telerik:RadComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="chkDays" Content="{Binding DaysText}"
Tag="{Binding DaysValue}" Checked="chkDays_Checked" />
</StackPanel>
</DataTemplate>
</telerik:RadComboBox.ItemTemplate>
</telerik:RadComboBox>
private void chkWeeks_Checked(object sender, RoutedEventArgs e)
{
//Here I want code for selecting all checkboxes.
}
The items that you bound the ComboBox to should have a property like IsSelected, then you should bind IsChecked of the data-template CheckBox to that. Then you just need to iterate over the source collection and set IsSelected=true on all items.
e.g.
public class MyClass : MyBaseClass // Whatever you may have called it,
{
public bool IsSelected { ... }
public string DaysText { ... }
//...
}
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected}" Content="{Binding DaysText}" Tag="{Binding DaysValue}" />
</StackPanel>
</DataTemplate>
//In the handler that is supposed to select all
foreach (var item in MonthDaysList) item.IsSelected = true;
Of course the property needs to have change notifications.
(Also a note on usability: I do not thing that ComboBoxes should contain CheckBoxes, if you need multiple item selection use a ListBox)
You need to take one more property isSelected as said by H.B.
add IsChecked="{Binding IsSelected}" to CheckBox tag in xaml file. Create one property in the appropriate class i.e. public bool isSeleted.......
When you get in to event chkWeeks_Checked() in this function get reference of the ComboBox item source like objList = (TypeCastYourClassType)YourComboBox.ItemSource;... Now the objList contains all checkbox items. Iterate through objList collection and get isSeleted property for each and every single item and that's done....
In your case
MonthDayList = (TypeCastYourClassType)rcbDays.ItemSource;
for(int i=0;i<MonthDayList.Count;i++)
{
MonthDayList[i].isSelected = true;
}
Here is some good discussion for allowing multiple values to be selected in the telerik combobox.
It uses checkbox within combobox
http://codedotnets.blogspot.in/2012/02/checkboxes-in-comboxes-to-allow.html
Thanks :)

Binding TextBlock based on selection in ComboBox

When I make selection in ComboBox, and then type some text in TextBox, I want to have visible AutoSuggestion list of ID or FirstName or LastName (based on ComboBox Selection) that contains typed string in TextBox. Like this, now it works only for FirstName.
I have problem to somehow set dynamically binding for TextBlock.
Please Help.
Thanks in advance! Marina
I have ComboBox:
<ComboBox Height="23" Name="cbAttrib" Width="120" Margin="0,8,0,0">
<ComboBoxItem>ID</ComboBoxItem>
<ComboBoxItem>FirstName</ComboBoxItem>
<ComboBoxItem>LastName</ComboBoxItem>
</ComboBox>
I have TextBox:
<TextBox Name="txtSearch" TextChanged="txtAutoSuggestName_TextChanged"/>
And this ListBox:
<ListBox Name="listBoxSuggestion" Visibility="Hidden" SelectionChanged="ListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock DataContext="{Binding FirstName}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and in code I have this methods:
private void txtAutoSuggestName_TextChanged(object sender, TextChangedEventArgs e)
{
listBoxSuggestion.Items.Clear();
if (txtSearch.Text != "")
{
ComboBoxItem cb = (ComboBoxItem)cbAttrib.SelectedItem;
Collection<Person> namelist = proxy.PersonSearch(txtSearch.Text, cb.Content.ToString());
if (namelist.Count > 0)
{
listBoxSuggestion.Visibility = Visibility.Visible;
foreach (var obj in namelist)
{
listBoxSuggestion.Items.Add(obj);
}
}
}
else
{
listBoxSuggestion.Visibility = Visibility.Hidden;
}
}
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0)
{
txtSearch.Text = (e.AddedItems[0] as Person).FirstName.ToString();
listBoxSuggestion.Visibility = System.Windows.Visibility.Hidden;
}
}
You are not binding the Text so nothing will display
You just bind the DataContext, which does nothing if there are no additional bindings which will be relative to it. Just swap that (or add Text="{Binding}" which will bind to the DataContext which is the FirstName) and if your logic is correct it should work.
(Instead of clearing and adding to Items you should just set the ItemsSource instead. listBoxSuggestion.ItemsSource = namelist;)
Edit: To make the binding work for different suggestions change the binding path to Value and make the ItemsSource a collection of some simple objects with a Value property (e.g. use LINQ and anonymous objects).

Xaml Binding outside itemtemplate

I would like to bind data of my listbox. Imagine I have something like :
<ListBox ItemsSource="{Binding MyList}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text={Binding Value} />
<TextBlock Text={Binding AbsoluteValue} />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
MyList contains an observable collection of an object that has a property named "Value"
AbsoluteValue is a property of the view model, as the MyList property.
Of course, the seconde textbox will have always the same value, but it is what I want :)
How can I tell the binding that the datacontext is not the same for the second textbox ?
Thanks in advance for any help
EDIT : my real sample is a StackPanel.
I've tryed
private void StackPanel_Loaded(object sender, RoutedEventArgs e)
{
StackPanel stackPanel = sender as StackPanel;
stackPanel.SetBinding(StackPanel.VisibilityProperty, new Binding("Loaded") { Source = DataContext, Mode = BindingMode.TwoWay });
}
but it's not working
XAML:
<TextBlock x:Name="tbAbsoluteValue" Loaded="AbsoluteValue_Loaded" />
Codebehind:
void AbsoluteValue_Loaded(object sender, RoutedEventArgs e)
{
TextBlock absoluteValue = sender as TextBlock;
absoluteValue.SetBinding(TextBlock.TextProperty, new Binding("AbsoluteValue") { Source = VIEW_MODEL_OBJECT, Mode = BindingMode.TwoWay });
}
That's one way to achieve what you want, you could also use a converter too, or create a StaticResource in your Resources for the VM and bind to that as a source.

Resources