|
1 | 1 | using System; |
| 2 | +using System.Collections.Generic; |
2 | 3 | using System.Diagnostics; |
3 | 4 | using System.IO; |
| 5 | +using System.Linq; |
4 | 6 | using System.Windows; |
| 7 | +using System.Windows.Controls; |
5 | 8 | using System.Windows.Media; |
6 | 9 | using System.Windows.Shapes; |
7 | 10 | using unvell.ReoGrid.CellTypes; |
@@ -279,16 +282,196 @@ private void AddDemoSheet3() |
279 | 282 |
|
280 | 283 | // information cell |
281 | 284 | 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 | + } |
283 | 292 |
|
284 | 293 | private void ShowText(Worksheet sheet, string text) |
285 | 294 | { |
286 | 295 | sheet[19, 0] = text; |
287 | 296 | } |
288 | | - #endregion // Demo Sheet 3 : Built-in Cell Types |
289 | 297 |
|
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) |
292 | 475 | { |
293 | 476 | grid.Reset(); |
294 | 477 | } |
|
0 commit comments