WPF FAQ - ItemsControl

Find answers for the most frequently asked questions
Expand All Collapse All

This same logic can be used to access the ItemsPresenter of other ItemsControls like ListView, etc.

[C#]
public partial class RetrieveItemsPanelDemo : Window
{
    public RetrieveItemsPanelDemo()
    {
        InitializeComponent();
        ListBox listBox = new ListBox() { ItemsSource = Enumerable.Range(0, 10) };
        this.Content = listBox;
        listBox.Loaded += delegate
        {
            VirtualizingStackPanel itemsPanel = listBox.GetVisualChild();
            if (itemsPanel != null && itemsPanel.IsItemsHost)
            {
                itemsPanel.PreviewMouseLeftButtonDown += delegate { MessageBox.Show('WPF'); };
            }
        };
    }
}

public static T GetVisualChild(this Visual referenceVisual) where T : Visual
{
    Visual child = null;
    for (Int32 i = 0; i < VisualTreeHelper.GetChildrenCount(referenceVisual); i++)
    {
        child = VisualTreeHelper.GetChild(referenceVisual, i) as Visual;
        if (child != null && (child.GetType() == typeof(T)))
        {
            break;
        }
        else if (child != null)
        {
            child = GetVisualChild(child);
            if (child != null && (child.GetType() == typeof(T)))
            {
                break;
            }
        }
    }
    return child as T;
}

Permalink

The fact that you have duplicate entries probably suggests that you are binding to the wrong data source. But, in any case, there are possibly valid scenarios where this is necessary. Here is a solution.

One way is to group the list by name using CollectionViewSource and then bind the Groups to the ListBox. Here is some code:

(for better code formatting, look at this thread: Distinct Value Filter For ListBox

If you Contracts collection is like this:

[C#]
public class Contracts : List    
    {   
        public Contracts()   
        {   
            this.Add(new Contract() { ContractKey = '1', Name = 'John' });   
            this.Add(new Contract() { ContractKey = '2', Name = 'Bill' });   
            this.Add(new Contract() { ContractKey = '3', Name = 'Bill' });   
        }   
    }   
  
    public class Contract   
    {   
        public string ContractKey { get; set; }   
        public string Name { get; set; }   
    }   

Then you can use the CollectionViewSource to bind to it and group the colelction by Name as follows:

[XAML]
  
      
  
           
  
           
              
                   
              
          
  
      
  
      
         	   
          
      
  

This will render the listbox the way you want – ignoring the duplicate names. You can then interpret the selected item as follows:

[XAML]
private void lb_SelectionChanged(object sender, SelectionChangedEventArgs e)   
        {   
            CollectionViewGroup groupSelected = ((CollectionViewGroup)e.AddedItems[0]);   
            string name = groupSelected.Name;   
            // These contain the items within the group   
            //groupSelected.Items;   
        }   
Permalink

You can apply a menu control style on a toolbar by using the Toolbar.MenustyleKey Property. This can be done with the following code snippet,

[XAML]
  <window.resources>
        <style x:key="{x:Static ToolBar.MenuStyleKey}" targettype="Menu">
            <Setter Property='FontSize' Value='14'/>
            <Setter Property='FontStyle' Value='Oblique'/>
            <Setter Property='FontWeight' Value='Bold'/>
            <Setter Property='Background' Value='AliceBlue'/>
        </style>
   </window.resources>
 
<grid>
   <toolbar>
            <menu>
                <menuitem header="File">
                    <menuitem header="New">
                        <menuitem header="Project">
                        <menuitem header="File">
                    </menuitem>
                </menuitem>
            </menuitem></menuitem></menu>
        </toolbar>
</grid>
Permalink

Share with

Couldn't find the FAQs you're looking for?

Please submit your question and answer.