WPF How do I find which ListBox item was clicked - wpf

I have a WPF application in which there's a listbox filled with items of type 'Match'.
How do I make the button(contained within the item) actually select the item so that I might extract the value?
Here is my code: neither works since clicking the button doesn't actually select the item
private void LayButton_Click(object sender, RoutedEventArgs e)
{
var x = (Market)ListBoxSelectedMarket.SelectedItem;
var y = (sender as ListBoxItem);
}
Thanks

You should be able to use the DataContext from the clicked Button and get the ListBoxItem container from there, and then select it.
private void LayButton_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
var dataContext = button.DataContext;
ListBoxItem clickedListBoxItem = ListBoxSelectedMarket.ItemContainerGenerator.ContainerFromItem(dataContext) as ListBoxItem;
clickedListBoxItem.IsSelected = true;
}

If you are binding to an object an alternative method could be (in VB)
This then gives you an instance of your object to play with and saves you having any mapping fields on the listbox
Private Sub OTC_Settled_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Dim pr_YourObject As New YourObject
Dim btn As Button = CType(sender, Button)
OTC = DirectCast(btn.DataContext, pr_YourObject)
End Sub

I haven't done much WPF programming, but you could try getting the parent of the button if it works the same as a WinForms container object.

Related

How to change the string format of a datagrid column in WPF with vb.net programmatically?

Basically, what I want to do is the WinForm Datagridview equivalent of dgvPreview.Columns(4).DefaultCellStyle.Format = "#,##0.00"
But instead of Datagridview, it's with Datagrid in WPF. Best I can do is assign a datatable to a Datagrid and change its alignment property.
DataGridPreview.ItemsSource = dtPreview.DefaultView
Private Sub BtnTest_Click(sender As Object, e As RoutedEventArgs) Handles BtnTest.Click
Dim txt As New DataGridTextColumn()
Dim s As New Style
s.Setters.Add(New Setter(TextBox.TextAlignmentProperty, TextAlignment.Right))
txt.CellStyle = s
DataGridPreview.Columns(4).CellStyle = s
'dgvPreview.Columns(4).DefaultCellStyle.Format = "#,##0.00"
End Sub
Please point me in the right direction. I'm trying to migrate from Winforms to WPF. And as much as possible I want to do this programmatically. I have also tried using the AutoGeneratingColumn but I can't figure it out.
If e.Column.Header.ToString = "Amount" Then
Dim dg As DataGridTextColumn = e.Column
dg.Binding.StringFormat = "#,000.00"
End If
If you are using AutoGeneratingColumn, the best time to update the StringFormat is on AutogeneratingColumn event. Column's binding serves as a blueprint for the individual cells' binding, so for some updates it is important to do them before the cells are created. In C# it will be something like this:
public MainWindow()
{
InitializeComponent();
grid.ItemsSource = Enumerable.Range(0, 10).Select(s => new { Id = s });
}
private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
(e.Column as DataGridTextColumn).Binding.StringFormat = "0.000";
}

Need to determine which grid a double-click came from?

I think this should be fairly simple, but I've been looking through the properties in the signature for the handler that I'm using and I don't see any way to suss out what I'm looking for.
I have a fairly simple WPF app with two DataGrid controls in the same window. I have a double click event defined in the XAML like so:
<DataGrid.ItemContainerStyle>
<Style TargetType="DataGridRow">
<EventSetter
Event="MouseDoubleClick"
Handler="Row_DoubleClick"/>
</Style>
</DataGrid.ItemContainerStyle>
And in the code behind (do we call it that in WPF apps?) I have the Row_DoubleClick handler set up like so:
Private Sub Row_DoubleClick(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs)
Now the sub itself works fine and picks up the row that was double-clicked just fine. However, as I noted before I have two DataGrids that use this same sub for the double-click event. I realize one path might be to simply make two subs, but it seems like I should be able to use the one for both, and it's taking the exact same action in either case, just using the row from one DataGrid or the other.
It always defaults to the first, let's call it IncompleteGrid, if a row is selected even if the second DataGrid, let's call it CompleteGrid, is the the one being double clicked. I've been looking through the sender and e objects in debug mode, but I don't see any place or property I can check to see which grid the double-click is coming from.
Any ideas?
You can get the parent dataGrid from row by using VisualTreeHelper. Have this private method on your code (code is in C#, hope you can get it convert to VB easily):
private void Row_DoubleClick(object sender, MouseButtonEventArgs e)
{
DataGridRow row = sender as DataGridRow;
DataGrid senderDataGrid = FindAncestor<DataGrid>(row);
}
private T FindAncestor<T>(DependencyObject dependencyObject)
where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindAncestor<T>(parent);
}
VB Version:
Private Sub Row_DoubleClick(sender As Object, e As MouseButtonEventArgs)
Dim row As DataGridRow = TryCast(sender, DataGridRow)
Dim senderDataGrid As DataGrid = FindAncestor(Of DataGrid)(row)
End Sub
Private Function FindAncestor(Of T As DependencyObject)(dependencyObject As DependencyObject) As T
Dim parent = VisualTreeHelper.GetParent(dependencyObject)
If parent Is Nothing Then
Return Nothing
End If
Dim parentT = TryCast(parent, T)
Return If(parentT, FindAncestor(Of T)(parent))
End Function
This parameter should give you the information:
ByVal sender As System.Object
sender should be the grid that the double-click is coming from. (That's the meaning of sender -- the control that sent the event.)
You can cast sender to a DataGrid if you want to do specific stuff with it.
Edit: If sender is a DataGridRow instead of a DataGrid, then you could use this question to find the host DataGrid. (Using a RelativeSource or a CommandParameter seems to the accepted methods for this.)

How do I find the ContextMenuStrip that a ToolStripMenuItem belongs to?

I have a ContextMenuStrip where one of the items has a DropDownItems property that is a collection of dynamically added ToolStripMenuItem objects. When I handle the sub-item Click event, the sender is of type ToolStripMenuItem, but its Owner is a ToolStripDropDownMenu. I can't find how to determine the 'host' ContextMenuStrip from this. It has no Owner property of its own, and Parent returns null.
When I use this adaptation of the code posted by #Steve below:
Dim dropDownItem = DirectCast(sender, ToolStripDropDownItem)
Dim menu As ContextMenuStrip = DirectCast((((dropDownItem.DropDown).OwnerItem).OwnerItem).Owner, ContextMenuStrip)
Dim grid = menu.SourceControl
then menu.SourceControl is Nothing, yet when I handle a top level, i.e. non-dropdown menu item's click like this
Dim item As ToolStripMenuItem = DirectCast(sender, ToolStripMenuItem)
Dim strip As ContextMenuStrip = DirectCast(item.Owner, ContextMenuStrip)
Dim grid As DataGridView = DirectCast(strip.SourceControl, DataGridView)
then I get the grid I was looking for.
If I understand correctly, you want to reach the ContextMenuStrip object from inside an Click event of a ToolStripMenuItem belonging to a ToolStripDropDownMenu.
If this is the case then
private void TestToolStripMenuItem_Click(object sender, EventArgs e)
{
ToolStripDropDownItem x = sender as ToolStripDropDownItem;
if (x != null)
{
ContextMenuStrip k = (((x.DropDown).OwnerItem).OwnerItem).Owner as ContextMenuStrip;
k.ForeColor = Color.Red; // as an example.
}
}

How to redirect events from a WPF UserControl to WinForm?

I have a winform with a wpf usercontrol on it (ElementHost1). The usercontrol contains only a button. How can I know when the wpf button has been clicked in my winform? How can I "redirect" the events from wpf usercontrol to winform?
Thanks.
This link might be helpful to you.
Or a simple event handling in VB.NET
Public Event ClickMe()
Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
RaiseEvent ClickMe()
End Sub
Then in your actual window you can have this:
Public Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
AddHandler SampleClick1.ClickMe, AddressOf Sample_Click
End Sub
Private Sub Sample_Click()
MessageBox.Show("This is a proof!")
End Sub
That SampleClick1 variable is from the designer code generated available to the form for your use.
Friend WithEvents ElementHost1 As System.Windows.Forms.Integration.ElementHost
Friend SampleClick1 As WindowsApplication1.SampleClick
Here is the one solution i found
in UserControl1.Xaml.cs
public static RoutedEvent ChkBoxChecked = EventManager.RegisterRoutedEvent("CbChecked", RoutingStrategy.Bubble,
typeof(RoutedEventHandler), typeof(CheckBox));
public event RoutedEventHandler CbChecked
{
add
{
AddHandler(ChkBoxChecked, value);
}
remove
{
RemoveHandler(ChkBoxChecked, value);
}
}
private void cbTreeView_Checked(object sender, RoutedEventArgs e)
{
RoutedEventArgs args = new RoutedEventArgs(ChkBoxChecked);
RaiseEvent(args);
}
Now in MainForm Form1 shown event we can add CbChecked event
private void Form1_Shown(object sender, EventArgs e)
{
this.elemetHost1.CbChecked += new System.Windows.RoutedEventHandler(wpfusercontrol_CbChecked);
//elementHost1 is the name of wpf usercontrol hosted in Winform
}
void elementHost1_CbChecked(object sender, System.Windows.RoutedEventArgs e)
{
//This event will raise when user clicks on chekbox
}
i am facing an issue here.i am rasing the same event in Form1 for all checkbox clickevents in UserControl1.so i want to know which checkbox is clicked in the mainform.i tried to see in the RoutedEventArgs e....but doesnt help
how to know which checkbox is clicked in the mainform

Retrieve Value on Mouse Click for WPF Column Series

I have a simple chart with two column series containing all months in the year. I want to filter a list view that show detailed information for the selected month. I can capture the event via MouseDown on the ColumnSeries but I'm not sure how to get to the month in the column series.
<DVC:ColumnSeries Title=" Expenditures" IndependentValueBinding="{Binding Path=Month}"
DependentValueBinding="{Binding Path=Amt}"
ItemsSource="{Binding Path=ActivityExpenditureSeries}"
MouseDown="ColumnSeries_MouseDown" />
I'm sure I could do some fancy WPF databinding to the selected ColumnSeries for the listviews ItemsSource but this is where I'm heading:
Private Sub ColumnSeries_MouseDown(ByVal sender As System.Object,
ByVal e As System.Windows.Input.MouseButtonEventArgs)
' This is the functionality I'm looking for...
Dim selectedColumn As String
FilterListView(selectedColumn)
End Sub
Set the IsSelectionEnabled=True on the series and added a SelectionChanged event to the same series.
Private Sub colSeries_adjExpenditure_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs)
Dim cs As ColumnSeries = CType(sender, ColumnSeries)
Dim dp As MyDataPoint = CType(cs.SelectedItem, MyDataPoint)
End Sub
Set the IsSelectionEnabled=True on the series and added a SelectionChanged event to the same series.
System.Windows.Controls.DataVisualization.Charting.ColumnSeries cs = (System.Windows.Controls.DataVisualization.Charting.ColumnSeries)sender;
System.Data.DataRowView dp = (System.Data.DataRowView)cs.SelectedItem;
tbkName.Text = dp.Row[1].ToString();
tbkSalary.Text = dp.Row[0].ToString();
Example in C#:
Set the IsSelectionEnabled=True on the series and added a SelectionChanged event to the same series.
Name Space:
using System.Windows.Controls.DataVisualization.Charting;
Method:
private void ColumnSeries_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ColumnSeries cs = (ColumnSeries)sender;
KeyValuePair<string, int> kv = (KeyValuePair<string, int>)cs.SelectedItem;
Debug.WriteLine(kv.Key);
Debug.WriteLine(kv.Value);
}
[In C#]
Previous answers only allow clicking when selections are changed. Following code will enable clicking on columns independently of where you clicked earlier. It will also allow right clicking if needed (change event type)
<chartingToolkit:ColumnSeries DependentValuePath="Value" IndependentValuePath="Key" IsSelectionEnabled="True">
<chartingToolkit:ColumnSeries.DataPointStyle>
<Style TargetType="chartingToolkit:ColumnDataPoint">
<EventSetter Event="MouseLeftButtonUp" Handler="ColumnSeries_ColumnLeftClicked"/>
</Style>
</chartingToolkit:ColumnSeries.DataPointStyle>
</chartingToolkit:ColumnSeries>
private void ColumnSeries_ColumnLeftClicked(object sender, MouseButtonEventArgs e)
{
var key = ((ColumnDataPoint)sender).IndependentValue;
//etc
}

Resources