I have a list box representing the contents of a direcory. I want to allow dropping only on those items that represent directories themselves. I've tried two approaches:
First i set the itemsource of the listbox to a compositeCollection of all directory contents and tried to iterate through those with:
foreach (ListBoxItem lbItem in directoryExplorer.Items)
{
MessageBox.Show(lbItem.DataContext.GetType().ToString());
}
The messagebox comes up with 'Directory' or 'UserFile' for each item. I was hoping to have access to the items, check what they represent, and set AllowDrop as necessary.
My second approach was to add individual items like so:
ListBoxItem nxt;
foreach (Directory d in dir.childdirs)
{
MessageBox.Show(d.name);
nxt = new ListBoxItem();
nxt.DataContext = d;
nxt.AllowDrop = true;
nxt.Name = d.name;
directoryExplorer.Items.Add(nxt);
}
foreach (UserFile f in dir.childfiles)
{
MessageBox.Show(f.name);
nxt = new ListBoxItem();
nxt.AllowDrop = false;
nxt.DataContext = f;
nxt.Name = f.name;
directoryExplorer.Items.Add(nxt);
}
but then it just comes up blank.
look at mdm20's answer wpf treeview blues. I want to select an item
Just make an allowDrop property and bind it appropriately.
Related
I have a question regarding use of "Tag" :
I have a ListBox, or ListView, in which I have the name of my objects, I addes a "Tag" property to find its corresponding object :
foreach(Operation op_ass in ListOpAss1)
{
op_ass.getNom(Properties.Settings.Default.Langue);
ListViewItem item = new ListViewItem(op_ass.Nom);
item.Tag = op_ass;
listBoxAss1.Items.Add(op_ass.Nom);
}
Now what I would like, is when I select an item in my list(or several), make an action on corresponding objects. But how can I find them back?
For example I want to remove selected objects from a List, or get the list of Operation ID (without displaying ID in my list).
Looks like you are adding the property, op_ass.Nom into the listbox instead of the ListViewItem, item. Modify your code as follows:
foreach (Operation op_ass in ListOpAss1)
{
op_ass.getNom(Properties.Settings.Default.Langue);
ListViewItem item = new ListViewItem(op_ass.Nom);
item.Tag = op_ass;
// Add the list view item instead of op_ass.Nom
listBoxAss1.Items.Add(item);
}
Now you should be able to retrieve the tag from selected item/items as follows:
var operation = ((listBox1.SelectedItem as ListViewItem).Tag) as Operation;
Alternatively, you could think of using data binding as follows:
foreach (Operation op_ass in ListOpAss1)
{
op_ass.getNom(Properties.Settings.Default.Langue);
}
listBoxAss1.DataSource = ListOpAss1;
listBoxAss1.DisplayMember = "Nom";
And access the data bound object as follows:
var operation = listBox1.SelectedItem as Operation;
using foreach is kind of deprecated you can look into implemented functions in list of objects
ListOpAss1.ForEach(x=>
{
x.getNom(Properties.Settings.Default.Langue);
var item = new ListViewItem(x.Nom);
item.Tag = x;
listBoxAss1.Items.Add(x.Nom);
});
in order to select an item in a list you can use SingleOrDefalt() or Skip(count) take (count) for multiple files or you can run native querys with conditions to search the list like this
var items = collection.Where(x=> x.City == "Burgas").ToList(); //You can use select if you want only certain properties of the object to be selected
///then you can use that new item list to remove the objects from the collection list like this
items.ForEach(x=>
{
collection.Remove(x);
});
I have a group item. Then, each group in group item, i put it into a listview
var Groups = query.GroupBy(query => query.Name);
foreach (var group in Groups)
{
if (group.records.Count() > 2)
{
ListView listview = new ListView();
var itemsource = new ObservableCollection<FileProperties>();
var header = "";
foreach (var item in group.records)
{
header = item.Name;
itemsource.Add(new FileProperties(item.Name, item.Size, item.DateModified, item.Hash, item.Path, item.IsOrigin));
}
listview.ItemsSource = itemsource;
var itemsTemplate = (DataTemplate)this.Resources["Show"];
listview.ItemTemplate = itemsTemplate;
//test is mother listview
test.Items.Add(listview);
}
}
Now, i have a question, how can i update listview UI if i change value in group items without reset mother listview
The default ListView can be grouped by using CollectionViewSource. There is no need to create a child ListView for each group of the parent ListView.
My answer here shows how to create a grouped ListView, you may take a look. Or there are a bunch of demos on internet, you can googling them.
But the most important point here is that by using the default grouped ListView, we can simply create one data collection for the whole ListView, modify the items source collection to update the grouped children automatically, we don't need to create ObservableCollections for each group any more.
I'm trying to remove an item from a listBox after i have drag and dropped it, but when i do so i got a message saying i cant modify the listbox since its linked with a datasource.
The thing is that i want to remove the item only from the view of the listBox while keeping it in the datasource.
Here is what i have tried to do:
int indexSelec = listBox3.SelectedIndex;
listBox3.Items.Remove(listBox3.Items[indexSelec]);
Does anybody has a solution?
Thx
You should storage List Box items to List< string > then use that List to add or remove items from List Box. Here is example:
First add a new list: List<string> _items = new List<string>();
Now add items to list and display it on List Box:
_items.Add("One");
_items.Add("Two");
_items.Add("Three");
listBox1.DataSource = _items; //this will display added items to List Box
Adding items to List Box:
_items.Add("New Item " + DateTime.Now.Second);
listBox1.DataSource = null;
listBox1.DataSource = _items;
Removing items from List Box:
int selectedIndex = listBox1.SelectedIndex;
try
{
_items.RemoveAt(selectedIndex);
}
catch
{
}
listBox1.DataSource = null;
listBox1.DataSource = _items;
You cannot remove the ListBoxItem from the ListBox, because it is part of a ReadOnlyCollection.
But you can set its Visibility.
ListBoxItem c = (ListBoxItem) ListBox1.ItemContainerGenerator.ContainerFromItem(ListBox1.Items[0]);
c.Visibility = System.Windows.Visibility.Collapsed;
List<Profile> listProf = new List<Profile>();
...
...
foreach (Profile p in listProf)
{
ListViewItem Item = new ListViewItem();
Item.Text = p.Name;
Item.Tag = p;
ListView1.Items.Add(Item);
ListView2.Items.Add(Item);
}
In this instance how would I get this Item into both ListViews? I just get the error that I need to clone it. how can I do this? I'm not quite sure even the reason why a ListView would want to be so picky either.
How can I add an item to more than one ListViewCollection?
Try this:
foreach(var p in listProf)
{
var item = new ListViewItem{Text = p.Name, Tag = p};
ListView1.Items.Add(item);
ListView2.Items.Add((ListViewItem)item.Clone());
}
The reason the ListView is so "picky" is because the IsSelected flag in particular is kept at the ListViewItem level... so if you added it to multiple ListViews then selected in one would be selected in all.
Fortunately ListViewItem has a .Clone() method.
I am using a multi-selection ListPicker (the new one in the 7.1/Mango control toolkit from Nov '11).
My code is below - a "vanilla" use case for the ListPicker, except that I initialize the SelecetedItems dependency property with a new List so I can add things to it and properly initialize the selected state for the ListPicker. Although this issue repro's whether or not I do this...
The SummaryForSelectedItemsDelegate does get called when initializing the list (e.g. when I call contactPicker.SetValue(ListPicker.SelectedItemsProperty)), but NOT when I click the "done" button on the ListPicker (although my SelectionChanged event handler does get called).
Once I dismiss the ListPicker, I only get the string corresponding to the first selected item in the "summary" for the control (as opposed to the control calling my delegate and getting a comma-delimited list of selected items).
Is this a bug? Has anyone else run into this? Is there a workaround?
var contactPicker = new ListPicker()
{
MinWidth = minWidth,
ExpansionMode = ExpansionMode.FullScreenOnly,
SelectionMode = SelectionMode.Multiple,
SummaryForSelectedItemsDelegate = (list) => { return CreateCommaDelimitedList(list); },
IsTabStop = true
};
contactPicker.ItemsSource = listOfItems;
contactPicker.DisplayMemberPath = "Name";
contactPicker.SetValue(ListPicker.SelectedItemsProperty, new List<Item>());
// initialize the list picker selected values
foreach (var contactRef in listOfSelectedContacts)
contactPicker.SelectedItems.Add(contactRef);
contactPicker.SelectionChanged += new SelectionChangedEventHandler((o, ea) =>
{
// add all the newly added items
foreach (var added in ea.AddedItems)
{
Item addedItem = added as Item;
if (addedItem == null)
continue;
listOfSelectedContacts.Items.Add(addedItem);
}
// remove all the newly removed items
foreach (var removed in ea.RemovedItems)
{
Item removedItem = removed as Item;
if (removedItem == null)
continue;
listOfSelectedContacts.Items.Remove(removedItem);
}
});
I should have posted my my summary delegate... which is actually where my bug was :-(
Even though I was creating the SelectedItems as a List, and each of the elements in the IList passed in are typed "Item", the concrete type of the IList passed in is NOT List. Therefore the null check succeeds and the method returns null. And of course my breakpoint was right after that line so it looked like the method wasn't getting invoked. Duh.
private string CreateCommaDelimitedList(IList ilist)
{
IList<Item> list = ilist as IList<Item>;
if (list == null)
return null;
// build a comma-delimited list of names to display in a control
List<string> names = list.Select(it => it.Name).ToList();
StringBuilder sb = new StringBuilder();
bool comma = false;
foreach (var name in names)
{
if (comma)
sb.Append(", ");
else
comma = true;
sb.Append(name);
}
return sb.ToString();
}