Accessing other listbox item controls and properties on button click - c#

I'm currently binding an xml file to a listbox in C# WPF. Within the itemtemplate I added controls. as follows:
<DataTemplate x:Key="SinglecueTemplate">
<Grid Height="30" Width="425" Margin="3,3,0,3">
<Button Content="{Binding XPath=nr}" Width="30" Style="{DynamicResource CUEStyle_Button_Inhoudknopje}" Template="{DynamicResource CUEStyle_singlecueknopnummer}" Height="Auto" HorizontalAlignment="Left" Background="#FFABCCED" Foreground="White" IsEnabled="False"/>
<TextBlock x:Name="name" Margin="54,0,114.667,0" Width="Auto" VerticalAlignment="Center" FontSize="16" Foreground="Gray" Text="{Binding XPath=Name}"/>
<Button x:Name="playbutton" Width="30" Style="{DynamicResource CUEStyle_Button_Groot}" Template="{DynamicResource CUEStyle_Rondknopje}" Height="Auto" HorizontalAlignment="Right" Margin="0,0.55,74.737,-0.55" Content="u" FontFamily="Wingdings 3" Foreground="#FF0178D3" Opacity="1" BorderBrush="#FF0178D3" Click="playcue"/>
<Button Width="30" Style="{DynamicResource CUEStyle_Button_Groot}" Template="{DynamicResource CUEStyle_Rondknopje}" Height="Auto" HorizontalAlignment="Right" Margin="0,0.55,37.071,-0.55" Content="ยข" FontFamily="Wingdings 2" Foreground="Gray" Opacity="0.4"/>
<Button Width="15" Style="{DynamicResource CUEStyle_Button_Groot}" Template="{DynamicResource CUEStyle_kleinloopje}" Height="15" HorizontalAlignment="Left" Margin="15,0,0,-5.5" Content="Q" FontFamily="Wingdings 3" Foreground="White" FontWeight="Bold" FontSize="10.667" Opacity="1" VerticalAlignment="Bottom" BorderBrush="{x:Null}" Background="{x:Null}" IsEnabled="{Binding XPath=Loop}"/>
<TextBlock Margin="0,0,114.667,0" Width="81.07" VerticalAlignment="Center" FontSize="16" Foreground="Gray" Text="03:02:11" HorizontalAlignment="Right"/>
</Grid>
</DataTemplate>
Now when a the playbutton is clicked I want to acces other properties from that listboxitem, for example the text from the text block. I looked up on how to do this and came up with the following:
private void playcue(object sender, System.Windows.RoutedEventArgs e)
{
Button playcue = (Button)sender;
Textbox titel = (Textbox)playcue.DataContext;
MessageBox.Show(titel);
}
But the code above gives me an error stating that the type Textbox is unknown. Do I have to do something with the datatemplate so that I can acces other items within the template? Or is it possible to access sibling nodes from the datasource?
UPDATE
Answer found. Now for future reference:
private void playcue(object sender, System.Windows.RoutedEventArgs e)
{
Button playcue = (Button)sender;
XmlElement name = (XmlElement)playcue.DataContext;
MessageBox.Show(name.InnerText);
}
Returns all sibling values from the item
If you want to access a specific sibling you can do so:
MessageBox.Show(name.SelectSingleNode("Name").InnerXml);

First problem is that it's TextBox not Textbox (C# is case sensitive.)
Second, it's unlikely that your DataContext is a TextBox. It should be an item in your ItemsSource collection. So, if the user clicks the third button in the list, you should be looking at the 3rd item in your ItemsSource collection. Since it appears you are using XML as a data source, I would guess that the item should be an XElement or an XmlElement.
I suggest you change Textbox titel = (Textbox)playcue.DataContext; to the following:
XElement element = (XElement)playcue.DataContext;
or
XmlElement element = (XmlElement)playcue.DataContext;
You will also need to change your MessageBox statement as well.

Related

Getting selected item in ListView without selecting an Item on UI

I'm working on a WPF application where I've made a ListView on UI which is two-way binding enabled. This WPF application is being developed for a windows 10 based smartphone. So whenever a user taps an item in the list whose data source is data-binded to back data collection, I've to do some operation for that item in code behind.
Now the problem is, I always receive a null object from the below function whenever the user taps on the item.
CartItem selectedItem = (CartItem)lv_CartItems.SelectedItem;
I only get a filled item object when the user actually selects an item by clicking on ListViewItem rather than tapping on it.
I want to get the selected item when the user taps on it. Is there any workaround available in WPF this problem? I've stuck here
My ListViewItem template looks like this.
<ListView Name="lv_CartItems" Loaded="lv_CartItems_Loaded"
HorizontalAlignment="Center" ScrollViewer.CanContentScroll="False"
ScrollViewer.VerticalScrollBarVisibility="Visible"
Width="250" Height="230" SelectionMode="Single"
>
<ListView.ItemTemplate>
<DataTemplate>
<Viewbox>
<Grid Width="230" Height="110" >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width=".1*" />
<ColumnDefinition />
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width=".5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border BorderBrush="LightGray" BorderThickness="1"
Grid.Row="0" Grid.Column="0"
Grid.ColumnSpan="6" Grid.RowSpan="3" >
</Border>
<Viewbox Grid.Row="0" >
<Image Name="img_ItemImage"
Source="{Binding Image, Mode=TwoWay }"
Width="20" Height=" 25" />
</Viewbox>
<Viewbox Grid.Column="2" Grid.ColumnSpan="3" VerticalAlignment="Top" >
<TextBlock Name="lbl_ItemName" TextWrapping="Wrap" Width="180" Foreground="Gray"
Text="{Binding Name , Mode=TwoWay }" >
</TextBlock>
</Viewbox>
<Viewbox Grid.Row="1" Margin="10,0" VerticalAlignment="Top" >
<TextBlock Foreground="Gray" >Qty:</TextBlock>
</Viewbox>
<Viewbox Grid.Row="2" Margin="0,0" VerticalAlignment="Top" >
<StackPanel Orientation="Horizontal" >
<Button Name="btn_Minus" FontWeight="ExtraBold" Tag="{Binding SKU_No,Mode=TwoWay}" Padding="0" Width="12"
Resources="{StaticResource cartitembutton}" Click="btn_Minus_Click" >
<Image Source="/Resources\Icons\minus.png" ></Image>
</Button>
<Border BorderThickness="1" Margin="2,0" Width="13" CornerRadius="2" BorderBrush="LightGray" >
<TextBlock Name="lbl_Quantity" FontWeight="Bold" Foreground="Gray"
HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Quantity , Mode=TwoWay }" >
</TextBlock>
</Border>
<Button Name="btn_Increment" FontWeight="ExtraBold" Width="12"
Resources="{StaticResource cartitembutton}" Tag="{Binding SKU_No,Mode=TwoWay}"
Padding="0"
Click="btn_Increment_Click">
<Image Source="/Resources\Icons\union_10.png" ></Image>
</Button>
</StackPanel>
</Viewbox>
<Viewbox Grid.Row="1" Grid.Column="2" Margin="5,0"
HorizontalAlignment="Left" Grid.ColumnSpan="3" >
<TextBlock Name="lbl_Price" FontWeight="DemiBold"
Text="{Binding Price , Mode=TwoWay}" ></TextBlock>
</Viewbox>
<Viewbox Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="3"
VerticalAlignment="Top" Margin="0,0" >
<TextBlock Name="lbl_Appearence"
Text="{Binding Appearance , Mode=TwoWay }"
TextWrapping="Wrap" Foreground="Gray" Width="210" >
</TextBlock>
</Viewbox>
<Viewbox Grid.Column="5" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="2,2"
>
<Button Name="btn_DeleteItem"
Click="btn_DeleteItem_Click"
Resources="{StaticResource cartitembutton}" >
<Image Source="/Resources/Icons/delete.png" ></Image>
</Button>
</Viewbox>
</Grid>
</Viewbox>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This is how a listVeiw looks like.
You don't actually want the selected item, you want to know which item contained the button that was clicked- whether that item is selected or not.
You can do this with events, but the more "correct" way to do it in WPF is with commands.
Commands are a pattern which separate the logic of an action (e.g. deleting an item) from the visual component that triggers the action (e.g. the button the user clicks). A command includes a parameter, which you can use to specify which item the command is being executed on. There are a couple different types on commands in WPF, but I'll be explaining using RoutedCommand.
In your case you'd first declare your command(s) in your Window:
public static readonly RoutedCommand DeleteItemCommand =
new RoutedCommand("DeleteItem", typeof(MainWindow));
private void OnCanExecuteDeleteItem(object sender , CanExecuteRoutedEventArgs e)
{
e.CanExecute = e.Parameter != null;
}
private void OnExecuteDeleteItem(object sender, ExecutedRoutedEventArgs e)
{
SomeType item = (SomeType)e.Parameter;
//Actually delete the item
}
And you'd add a CommandBinding to your Window which links the command to the methods which handle it:
<Window.CommandBindings>
<CommandBinding Command="local:MainWindow.DeleteItemCommand" CanExecute="OnCanExecuteDeleteItem" Executed="OnExecuteDeleteItem"/>
</Window.CommandBindings>
And finally, to link your delete Button to the command:
<Button Name="btn_DeleteItem" Resources="{StaticResource cartitembutton}" Command="local:MainWindow.DeleteItemCommand" CommandParameter="{Binding}">
<Image Source="/Resources/Icons/delete.png"/>
</Button>
CommandParameter="{Binding}" works because your Button is inside a DataTemplate, so its DataContext will be the item that is being displayed. This lets you check e.Parameter in your routed event methods to see which item is being interacted with.

Extended Textbox is behind other elements in WPF

It's the first time i am learning WPF with C#.
So i have a textbox which is extended when i click on a button. The problem is when i extend it,it remains behind my other elements(textboxes etc...)
Here is the xml code for the textbox.
<StackPanel Grid.Column="1" Grid.ColumnSpan="4" Grid.Row="3" Grid.RowSpan="5" Panel.ZIndex="0" Visibility="Collapsed" Name="descriptionPanel" Margin="2,0,0,0" Background="White">
<Border BorderBrush="DarkGray" BorderThickness="1" CornerRadius="5">
<StackPanel Orientation="Horizontal">
<TextBox Name="descriptionTextBoxExtended"
Margin="10,10,10,10"
Style="{StaticResource expandedTextBox}"
Text="{Binding Path=Description, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true, TargetNullValue=''}"
IsReadOnly="{Binding RelativeSource={RelativeSource AncestorLevel=1,AncestorType=Control}, Path=SecurityLevel2ReadOnly, Mode=OneWay}"
/>
<Button Name="descriptionHide" Style="{StaticResource MinusButton}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,10,10" Click="descriptionHide_Click" />
</StackPanel>
</Border>
</StackPanel>
And here is the C#
private void exDescription_Click(object sender, RoutedEventArgs e)
{
descriptionPanel.Visibility = Visibility.Visible;
}
This is how it looks when i run it before i click the extend button:
And this is how it looks when i extend the textbox:
I want all the highlighted components to be behind the textbox.
You should give us the code of the other elements beside "descriptionPanel", but as mm8 pointed out, it seems that your elements are not in the same Panel.

How to open Popup by clicking on grid view item in windows store app?

I want to open popup by clicking on button in gridView element, inside popup I have three options by clicking on that option I want to navigate to another page with the id of the element
i want to open popup on click on button inside the gridView element my code looks like :-
<GridView x:Name="Test" Grid.Row="1" Margin="20,20,20,20" >
<GridView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<Button Background="Red" HorizontalAlignment="Left" VerticalAlignment="Top" Height="100" Content="OpenPopup" Click="Button_PointerPressed"></Button>
<Popup x:Name="Mypopup">
<TextBlock Text="hi"/>
</Popup>
<StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
<TextBlock Text="{Binding Title}" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextBlockStyle}" Height="60" Margin="15,0,15,0"/>
<TextBlock Text="{Binding Subtitle}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
</StackPanel>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
on click event
private void Button_PointerPressed(object sender, RoutedEventArgs e)
{
Mypopup.isopen = true;
}
Error:-The name 'Mypopup' does not exist in the current context
I am a newbie.. so help me
All you have to do is on the Onclick event of your gridview's button do the following code :
popup.isopen = true
Then in your popup if you want to navigate to another page all you have to do is use Navigate on the proper event
Frame.Navigate(typeof(YourPage),YourID);
EDIT : If the buttons in your gridview are added through code and you want to do the event on those then make sure that they have different names such as : GrdButton1/GrdButton2 and then give them an event dynamicly
If they are added in the XAML then simply add it an event there
<Button x:Name="ButtonTest"
Click="ButtonTest_Click"/>
If none of this answers your question please add more details to it

How to acces text of textblock inside a dynamic stackpanel in wp8?

I have a data binded ListBox containing a stackpanel, which contains a number of textbox and the text is being dynamically loaded from server. This is how the XAML looks like-
<ListBox x:Name="SearchColl_List" ItemsSource="{Binding }" >
<ListBox.ItemTemplate>
<DataTemplate>
<!--Main Stack-->
<StackPanel x:Name="Coll_Stack" Orientation="Vertical"
Margin="10,0,6,20"
Tap="StackPanel_Tap">
<TextBlock x:Name="Name_Text"
Text="{Binding Name}"
FontSize="20"
Width="450"
HorizontalAlignment="Left"
Foreground="#33706b"
TextWrapping="Wrap"
/>
<TextBlock Text="{Binding Stream}"
Width="450"
HorizontalAlignment="Left"
FontSize="20"
Foreground="Green"
TextWrapping="Wrap"
/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I have an event "StackPanel_Tap" and I want to access the Text in "Name_Text"(TextBox) for the stack panel element that is being tapped. I want to access the text in following Method Stub...
private void StackPanel_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
//Access the Text in "Name_Text" for current element that is tapped
}
Try this:
((sender as StackPanel).FindName("Name_Text") as TextBlock).Text
Another way would be:
(sender as StackPanel).Children[0].Text

How to get the value of the checked radiobutton in wpf

I have four RadioButtons in a grid panel, but when I do this:
<GroupBox x:Name="radioButtons">
<RadioButton Content="1" Height="16" HorizontalAlignment="Left" Margin="10,45,0,0" Name="status1" VerticalAlignment="Top" />
<RadioButton Content="2" Height="16" HorizontalAlignment="Left" Margin="10,67,0,0" Name="status2" VerticalAlignment="Top" />
<RadioButton Content="3" Height="16" HorizontalAlignment="Left" Margin="10,89,0,0" Name="status3" VerticalAlignment="Top" />
<RadioButton Content="4" Height="16" HorizontalAlignment="Left" Margin="10,111,0,0" Name="status4" VerticalAlignment="Top" />
</GroupBox>
It says that:
Error 1 The object 'GroupBox' already has a child and cannot add 'RadioButton'. 'GroupBox' can accept only one child.
And the last three RadioButtons say:
The property 'Content' is set more than once.
What's wrong with my GroupBox? Furthermore, in my code I want to access the RadioButton that is checked (preferably as an int). How do I do this? I tried to look in Google and I found a lot of results, but I couldn't understand any of them.
GroupBox can only hold 1 item, hence the error about trying to set the Content property of the GroupBox multiple times.
So, make that a Layout item and then put the RadioButtons inside it. Now, you set the Content once, which is the StackPanel, and that Layout item can hold many children -> RadioButtons.
<GroupBox x:Name="radioButtons">
<StackPanel>
<RadioButton Name="status1"
Height="16"
Margin="10,45,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="1" />
<RadioButton Name="status2"
Height="16"
Margin="10,67,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="2" />
<RadioButton Name="status3"
Height="16"
Margin="10,89,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="3" />
<RadioButton Name="status4"
Height="16"
Margin="10,111,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="4" />
</StackPanel>
</GroupBox>
As for your second question, Christian Mosers WPF Tutorial.net has a decent sample. If you don't understand it, you maybe should look at the topics Binding and Converter, first.
A very crude way to be notified of RadioButton checked in a non MVVM way:
private void RadioButtonChecked(object sender, RoutedEventArgs e) {
var radioButton = sender as RadioButton;
if (radioButton == null)
return;
int intIndex = Convert.ToInt32(radioButton.Content.ToString());
MessageBox.Show(intIndex.ToString(CultureInfo.InvariantCulture));
}
Then, in each of your RadioButtons in xaml, add Checked="RadioButtonChecked".
If you want many elements or controls then you have to put them in layout containers.
Grid
StackPanel
DockPanel
WrapPanel
Etc.....

Categories