Skip to content

Commit 24fd39a

Browse files
authored
Merge pull request #560 from yepeng2002/feature/WPFDropdownCell
Add WPF Dropdown Window Control Class for Cells
2 parents f3e8f60 + 704ff72 commit 24fd39a

File tree

2 files changed

+487
-32
lines changed

2 files changed

+487
-32
lines changed

DemoWPF/MainWindow.xaml.cs

Lines changed: 187 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Diagnostics;
34
using System.IO;
5+
using System.Linq;
46
using System.Windows;
7+
using System.Windows.Controls;
58
using System.Windows.Media;
69
using System.Windows.Shapes;
710
using unvell.ReoGrid.CellTypes;
@@ -279,16 +282,196 @@ private void AddDemoSheet3()
279282

280283
// information cell
281284
worksheet.SetRangeBorders(19, 0, 1, 10, BorderPositions.Top, RangeBorderStyle.GraySolid);
282-
}
285+
286+
// dropdown cell
287+
worksheet["B18"] = "Dropdown ListView:";
288+
worksheet["D18"] = "Choose...";
289+
worksheet["D18"] = new ListViewDropdownCell();
290+
worksheet.Ranges["D18"].BorderOutside = RangeBorderStyle.GraySolid;
291+
}
283292

284293
private void ShowText(Worksheet sheet, string text)
285294
{
286295
sheet[19, 0] = text;
287296
}
288-
#endregion // Demo Sheet 3 : Built-in Cell Types
289297

290-
#region Menu - File
291-
private void File_New_Click(object sender, RoutedEventArgs e)
298+
299+
class ListViewDropdownCell : DropdownCell
300+
{
301+
private readonly ListView listView;
302+
303+
public ListViewDropdownCell()
304+
{
305+
listView = new ListView
306+
{
307+
BorderThickness = new Thickness(0),
308+
SelectionMode = SelectionMode.Single,
309+
View = new GridView()
310+
};
311+
312+
this.DropdownControl = listView;
313+
314+
var gridView = (GridView)listView.View;
315+
gridView.Columns.Add(new GridViewColumn
316+
{
317+
Header = "Name",
318+
Width = 120,
319+
DisplayMemberBinding = new System.Windows.Data.Binding(nameof(ListViewItemData.Text))
320+
});
321+
gridView.Columns.Add(new GridViewColumn
322+
{
323+
Header = "Description",
324+
Width = 120,
325+
DisplayMemberBinding = new System.Windows.Data.Binding(nameof(ListViewItemData.SubText))
326+
});
327+
328+
// Create data items
329+
var items = new List<ListViewItemData>
330+
{
331+
new ListViewItemData { Group = "A", Text = "Apple", SubText = "Red fruit" },
332+
new ListViewItemData { Group = "A", Text = "Banana", SubText = "Yellow fruit" },
333+
new ListViewItemData { Group = "B", Text = "Watermelon", SubText = "Green fruit" },
334+
new ListViewItemData { Group = "B", Text = "Grape", SubText = "Purple fruit" }
335+
};
336+
337+
listView.ItemsSource = items;
338+
this.MinimumDropdownWidth = 300;
339+
340+
listView.PreviewMouseDoubleClick += ListView_MouseDoubleClick;
341+
listView.PreviewKeyDown += ListView_PreviewKeyDown;
342+
}
343+
344+
private void ListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
345+
{
346+
var listView = sender as ListView;
347+
var depObj = e.OriginalSource as DependencyObject;
348+
while (depObj != null && !(depObj is ListViewItem))
349+
depObj = VisualTreeHelper.GetParent(depObj);
350+
351+
if (depObj is ListViewItem listViewItem)
352+
{
353+
listView.SelectedItem = listView.ItemContainerGenerator.ItemFromContainer(listViewItem);
354+
}
355+
356+
CommitSelection();
357+
}
358+
359+
private void ListView_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
360+
{
361+
var listView = sender as ListView;
362+
363+
if (e.Key == System.Windows.Input.Key.Enter)
364+
{
365+
CommitSelection();
366+
e.Handled = true;
367+
}
368+
else if (e.Key == System.Windows.Input.Key.Escape)
369+
{
370+
PullUp();
371+
e.Handled = true;
372+
}
373+
else if (e.Key == System.Windows.Input.Key.Up || e.Key == System.Windows.Input.Key.Down)
374+
{
375+
// Handle up/down key selection
376+
int currentIndex = listView.SelectedIndex;
377+
int itemCount = listView.Items.Count;
378+
379+
if (itemCount > 0)
380+
{
381+
if (e.Key == System.Windows.Input.Key.Up)
382+
{
383+
// Up key: select previous item
384+
if (currentIndex > 0)
385+
{
386+
listView.SelectedIndex = currentIndex - 1;
387+
var item = listView.ItemContainerGenerator.ContainerFromIndex(currentIndex - 1) as ListViewItem;
388+
item?.Focus();
389+
}
390+
else
391+
{
392+
// If on first item, cycle to last item
393+
listView.SelectedIndex = itemCount - 1;
394+
var item = listView.ItemContainerGenerator.ContainerFromIndex(itemCount - 1) as ListViewItem;
395+
item?.Focus();
396+
}
397+
}
398+
else if (e.Key == System.Windows.Input.Key.Down)
399+
{
400+
// Down key: select next item
401+
if (currentIndex < itemCount - 1)
402+
{
403+
listView.SelectedIndex = currentIndex + 1;
404+
var item = listView.ItemContainerGenerator.ContainerFromIndex(currentIndex + 1) as ListViewItem;
405+
item?.Focus();
406+
}
407+
else
408+
{
409+
// If on last item, cycle to first item
410+
listView.SelectedIndex = 0;
411+
var item = listView.ItemContainerGenerator.ContainerFromIndex(0) as ListViewItem;
412+
item?.Focus();
413+
}
414+
}
415+
416+
// Ensure selected item is visible
417+
if (listView.SelectedItem != null)
418+
{
419+
listView.ScrollIntoView(listView.SelectedItem);
420+
}
421+
422+
e.Handled = true;
423+
}
424+
}
425+
else if (e.Key == System.Windows.Input.Key.Tab)
426+
{
427+
// Handle Tab key
428+
CommitSelection();
429+
e.Handled = true;
430+
}
431+
}
432+
433+
protected override void OnDropdownControlLostFocus()
434+
{
435+
PullUp();
436+
}
437+
438+
public override void PushDown()
439+
{
440+
base.PushDown();
441+
442+
// When dropdown panel opens, automatically select the item matching current cell content
443+
if (this.Cell?.Data is string text && listView.ItemsSource is IEnumerable<ListViewItemData> items)
444+
{
445+
var itemToSelect = items.FirstOrDefault(i => i.Text == text);
446+
if (itemToSelect != null)
447+
{
448+
listView.SelectedItem = itemToSelect;
449+
listView.ScrollIntoView(itemToSelect);
450+
}
451+
}
452+
}
453+
454+
private void CommitSelection()
455+
{
456+
if (listView.SelectedItem is ListViewItemData selectedItem)
457+
{
458+
this.Cell.Data = selectedItem.Text;
459+
PullUp();
460+
}
461+
}
462+
463+
// Data item class
464+
private class ListViewItemData
465+
{
466+
public string Group { get; set; }
467+
public string Text { get; set; }
468+
public string SubText { get; set; }
469+
}
470+
}
471+
#endregion // Demo Sheet 3 : Built-in Cell Types
472+
473+
#region Menu - File
474+
private void File_New_Click(object sender, RoutedEventArgs e)
292475
{
293476
grid.Reset();
294477
}

0 commit comments

Comments
 (0)