I have defined the ItemTemplate for the TreeView in the code behind C#. In that ItemTemplate, I have a CheckBox and a label defined in it. The Tag and Text properties of the CheckBox and label is binded with the data.
Now, I'd like to get the TreeViewItem object whenever the user clicks on the CheckBox. I used the click event on the CheckBox but that event didn't give me the TreeViewItem's object.
I would really appreciate if someone could explain the solution for it.
Here's the code written in C#:
public static void FillTree()
{
//assign treeview itemtemplate
BIMExplorerUserControl.Instance.BimTreeView.ItemTemplate = GetHeaderTemplate();
BIMExplorerUserControl.Instance.BimTreeView.ItemContainerGenerator.StatusChanged += new EventHandler(ItemContainerGenerator_StatusChanged);
foreach (var category in ViewModel.Instance.DefaultExplorerView)
{
BIMExplorerUserControl.Instance.BimTreeView.Items.Add(category);
}
}
public static DataTemplate GetHeaderTemplate()
{
//create the data template
DataTemplate dataTemplate = new DataTemplate();
//create stack pane;
FrameworkElementFactory stackPanel = new FrameworkElementFactory(typeof(StackPanel));
stackPanel.Name = "parentStackpanel";
stackPanel.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
// Create check box
FrameworkElementFactory checkBox = new FrameworkElementFactory(typeof(CheckBox));
checkBox.Name = "chk";
checkBox.SetValue(CheckBox.NameProperty, "chk");
checkBox.SetValue(CheckBox.TagProperty, new Binding());
checkBox.SetValue(CheckBox.MarginProperty, new Thickness(2));
checkBox.SetValue(CheckBox.TagProperty, new Binding() { Path = new PropertyPath("Name") });
checkBox.AddHandler(CheckBox.ClickEvent, new RoutedEventHandler(CheckedEvent));
stackPanel.AppendChild(checkBox);
// create text
FrameworkElementFactory label = new FrameworkElementFactory(typeof(TextBlock));
label.SetBinding(TextBlock.TextProperty, new Binding() { Path = new PropertyPath("Name") });
label.SetValue(TextBlock.ToolTipProperty, new Binding());
stackPanel.AppendChild(label);
//set the visual tree of the data template
dataTemplate.VisualTree = stackPanel;
return dataTemplate;
}
static void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
if (BIMExplorerUserControl.Instance.BimTreeView.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
foreach (var category in ViewModel.Instance.DefaultExplorerView)
{
TreeViewItem item = (TreeViewItem)BIMExplorerUserControl.Instance.BimTreeView.ItemContainerGenerator.ContainerFromItem(category);
if (item == null) continue;
item.IsExpanded = false;
if (item.Items.Count == 0)
{
foreach (var element in category.Elements)
{
item.Items.Add(element);
}
}
}
}
}
private static void CheckedEvent(object sender, RoutedEventArgs e)
{
CheckBox checkbox = (CheckBox)e.Source;
var name = checkbox.Tag.ToString();
}
You could use the following helper method to get a reference to the CheckBox's parent TreeViewItem in the visual tree:
private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindParent<T>(parent);
}
Usage:
private static void CheckedEvent(object sender, RoutedEventArgs e)
{
CheckBox checkbox = (CheckBox)sender;
var name = checkbox.Tag.ToString();
TreeViewItem tvi = FindParent<TreeViewItem>(checkbox);
//...
}
Related
I encounter some issues with my project. I have a moderntab that I fill of link by a request into a database. The result of my request return a list of string that will be the displayname of the link of my moderntab. I create all the link in behind code, and I want that when I click into a link, the content of the usercontrol change in function of the displayname.
Currently, I know how to take the displayname when the it detect that I change source. But I want to have the same Source for all the link, and the content of the usercontrol change in function of the displayname of the selected link.
That's my xaml code of the moderntab :
<Grid Style="{StaticResource ContentRoot}">
<mui:ModernTab Layout="List" Name="listEcole" SelectedSourceChanged="listEcole_SelectedSourceChanged"/>
</Grid>
That's is the code behind :
public ListEcoles()
{
InitializeComponent();
List<string> listEcoles = MainWindow._RE.ListEcoles();
foreach (string nomEcole in listEcoles)
listEcole.Links.Add(new Link() { DisplayName = nomEcole, Source = new Uri("/Controles/EcoleControl.xaml", UriKind.Relative) });
}
private void listEcole_SelectedSourceChanged(object sender, SourceEventArgs e)
{
var selectedLink = listEcole.Links.FirstOrDefault(x => x.Source == listEcole.SelectedSource);
if (selectedLink != null)
{
string selectedDisplayName = selectedLink.DisplayName;
MessageBox.Show(selectedDisplayName);
}
}
It doesn't work here because every sources of my link are the same, so the event never proceed.
Can some one help me please.
Handle another event like the PreviewMouseLeftButtonUp then. You could use a helper method that finds the ListBoxItem in the visual tree and then get a reference to the corresponding Link object using the ListBoxItem's DataContext property.
Try this:
public ListEcoles()
{
InitializeComponent();
List<string> listEcoles = MainWindow._RE.ListEcoles();
foreach (string nomEcole in listEcoles)
listEcole.Links.Add(new Link() { DisplayName = nomEcole, Source = new Uri("/Controles/EcoleControl.xaml", UriKind.Relative) });
listEcole.PreviewMouseLeftButtonUp += ListEcole_MouseLeftButtonUp;
}
private void ListEcole_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
ListBoxItem lbi = e.OriginalSource as ListBoxItem;
if (lbi == null)
{
lbi = FindParent<ListBoxItem>(e.OriginalSource as DependencyObject);
}
if (lbi != null)
{
Link selectedLink = lbi.DataContext as Link;
if (selectedLink != null)
{
string selectedDisplayName = selectedLink.DisplayName;
MessageBox.Show(selectedDisplayName);
}
}
}
private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindParent<T>(parent);
}
I am dynamically populating a ListPicker using a basic List in code behind. On the SelectionChanged event I need to determine the name of the item that the user selected. Currently what I have is as follows, but I cannot get the Name of the item?
XAML
<toolkit:ListPicker x:Name="lp" Visibility="Collapsed"/>
XAML.CS
//Populate the ListPicker
List<ListPickerItem> l = new List<ListPickerItem>();
l.Add(new ListPickerItem { Name = "Flip_Vertical", Content = AppResources.App_Flip_Vertical });
l.Add(new ListPickerItem { Name = "Flip_Horizontal", Content = AppResources.App_Flip_Horizontal });
l.Add(new ListPickerItem { Name = "Flip_Both", Content = AppResources.App_Flip_Both });
lp.ItemsSource = l;
lp.Visibility = Visibility.Visible;
...
void lp_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (lp.SelectedIndex != -1)
{
var item = (sender as ListPicker).SelectedItem;
if (item != null)
{
//switch () //Need to determine the Name of the currently selected item?
}
}
}
EDIT**
Cannot call Name when setting item
Using var is not that great since SelectedItem is an object
Convert it to
string name = ((ListPickerItem)item).Name;
im trying to get the value of a textblock in a listbox when the item is selected
public MainPage()
{
Startup.checknetwork();
InitializeComponent();
this.Loaded += new RoutedEventHandler(Load_List);
}
private void Load_List(object sender, RoutedEventArgs e)
{
XDocument loadedData = XDocument.Load("List.xml");
List<XElement> elements = loadedData.Descendants("ItemTitle").ToList();
List<RSSItem> aux = new List<RSSItem>();
foreach (XElement rssItem in elements)
{
RSSItem rss = new RSSItem();
rss.Title1 = rssItem.Element("Title").Value;
rss.Date1 = rssItem.Element("Uri").Value;
aux.Add(rss);
TextBlock One = new TextBlock();
One.Text = rss.Title1;
One.Tag = rss.Date1;
AListBox.Items.Add(One);
}
}
private void AList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var SelectedItem = ((TextBlock)sender).Tag as String;
}
everything loads up fine using debug.writeline it shows the correct textbox texts and tags the alist shows the list.
how ever if i select an item i just get an error
Could someone tell me what i am doing wrong
thanks
The SelectionChanged event send by ItemsControl. So the sender is ItemsControl not a selected item. You need SelectedItem not the sender.
In my winForm application I have added databound combobox column in a datagridview. User needs to be able to select an item from dropdown list or write in the combobox. But it wouldn't let me write in the combobox as datasource is set. This is my code:
var entityModel= new AdminEntities();
var filterPractice = (from b in entityModel.FILTER where b.PRACTICE != null select b.PRACTICE).Distinct().OrderBy(y => y);
dgvCboColumn(filterPractice, "PRACTICE");
private void dgvCboColumn(dynamic item, string colName)
{
int i = dgvLoadTable.Columns[colName].Index;
DataGridViewComboBoxColumn dgvCol = new DataGridViewComboBoxColumn();
dgvCol.DataSource=item;
dgvCol.DataPropertyName = colName;
dgvLoadTable.Columns.Insert(i, dgvCol);
dgvLoadTable.Columns[i].HeaderText = dgvLoadTable.Columns[i + 1].HeaderText;
dgvLoadTable.Columns[i + 1].Visible = false;
dgvLoadTable.Columns.RemoveAt(i + 1);
}
private void HandleEditShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
var cbo = e.Control as ComboBox;
if (cbo == null)
{
return;
}
cbo.DropDownStyle = ComboBoxStyle.DropDown;
cbo.Validating -= HandleComboBoxValidating;
cbo.Validating += HandleComboBoxValidating;
}
private void HandleComboBoxValidating(object sender, CancelEventArgs e)
{
var combo = sender as DataGridViewComboBoxEditingControl;
if (combo == null)
{
return;
}
if (!combo.Items.Contains(combo.Text))
{
var comboColumn = this.dgvLoadTable.Columns[this.dgvLoadTable.CurrentCell.ColumnIndex] as DataGridViewComboBoxColumn;
combo.Items.Add(combo.Text);
comboColumn.Items.Add(combo.Text);
this.dgvLoadTable.CurrentCell.Value = combo.Text;
}
}
Can anyone tell me how can I make the combobox editable, please?
you can manually get the items frm datasource using Oledb or Ado recordset nd fill de comboBox manually by using for loops.. so basically you can also edit the items..
I've got datagrid with context menu. It is initialized programatically:
contextMenu = new ContextMenu();
foreach (var col in this.Columns)
{
var checkBox = new MenuItem()
{
Header = col.Header
};
Binding myBinding = new Binding("Visibility");
myBinding.Mode = BindingMode.TwoWay;
myBinding.Converter = new IsCheckedToVisibilityConverter();
checkBox.DataContext = col;
checkBox.SetBinding(MenuItem.IsCheckedProperty, myBinding);
checkBox.Click += checkBox_Click;
checkBox.Checked += checkBox_Checked;
checkBox.Unchecked += checkBox_Unchecked;
contextMenu.Items.Add(checkBox);
}
It works great, but i would like to stay open context menu after check\uncheck menuitems. Any ideas ?
After adding checkBox.StaysOpenOnClick = true; works as expected
contextMenu = new ContextMenu();
foreach (var col in this.Columns)
{
var checkBox = new MenuItem()
{
Header = col.Header
};
//binding
Binding myBinding = new Binding("Visibility");
myBinding.Mode = BindingMode.TwoWay;
myBinding.Converter = new IsCheckedToVisibilityConverter();
checkBox.DataContext = col;
checkBox.SetBinding(MenuItem.IsCheckedProperty, myBinding);
checkBox.Click += checkBox_Click;
checkBox.Checked += checkBox_Checked;
checkBox.Unchecked += checkBox_Unchecked;
checkBox.StaysOpenOnClick = true;
contextMenu.Items.Add(checkBox);
}
You can try:
private bool close= true;
private void CheckBox1_CheckedChanged(Object sender, EventArgs e)
{
close= false;
}
private void contextMenu_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
e.Cancel = !close;
CloseContextMenu = true;
}