397 lines
13 KiB
C#
397 lines
13 KiB
C#
using C4IT.FASD.Base;
|
|
using C4IT.MultiLanguage;
|
|
using FasdDesktopUi.Basics.Models;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Timers;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Controls.Primitives;
|
|
using System.Windows.Data;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Navigation;
|
|
using static C4IT.Logging.cLogManager;
|
|
|
|
namespace FasdDesktopUi.Basics.UserControls
|
|
{
|
|
public partial class ComboBoxPageable : UserControl, IFocusInvoker
|
|
{
|
|
#region Fields & Properties
|
|
|
|
private const int itemsPerPage = 10;
|
|
private const double searchDelayInMilliseconds = 350;
|
|
|
|
private int pageIndex = 0;
|
|
private int pageCount = 1;
|
|
private readonly Timer timer = new Timer(searchDelayInMilliseconds);
|
|
|
|
private readonly cF4sdHealthSelectionDataRequest searchData = new cF4sdHealthSelectionDataRequest() { Search = string.Empty, Page = 0, PageSize = itemsPerPage };
|
|
|
|
public int? ParentIndex { get; set; }
|
|
public UIElement ParentElement { get; set; }
|
|
|
|
|
|
public string ResetFilterLabel
|
|
{
|
|
get { return (string)GetValue(ResetFilterLabelProperty); }
|
|
set { SetValue(ResetFilterLabelProperty, value); }
|
|
}
|
|
|
|
public static readonly DependencyProperty ResetFilterLabelProperty =
|
|
DependencyProperty.Register("ResetFilterLabel", typeof(string), typeof(ComboBoxPageable), new PropertyMetadata(cMultiLanguageSupport.GetItem("Dialog.CloseCase.ResetFilter")));
|
|
|
|
public bool ResetFilter
|
|
{
|
|
get { return (bool)GetValue(ResetFilterProperty); }
|
|
set { SetValue(ResetFilterProperty, value); }
|
|
}
|
|
|
|
public static readonly DependencyProperty ResetFilterProperty =
|
|
DependencyProperty.Register("ResetFilter", typeof(bool), typeof(ComboBoxPageable), new PropertyMetadata(false, new PropertyChangedCallback(ResetFilterChanged)));
|
|
|
|
private static void ResetFilterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (!(d is ComboBoxPageable me))
|
|
return;
|
|
|
|
me.searchData.ResetFilter = me.ResetFilter;
|
|
me.InvokeSearchValueChanged();
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#region TotalItemCount
|
|
|
|
public int TotalItemCount
|
|
{
|
|
get { return (int)GetValue(TotalItemCountProperty); }
|
|
set { SetValue(TotalItemCountProperty, value); }
|
|
}
|
|
|
|
public static readonly DependencyProperty TotalItemCountProperty =
|
|
DependencyProperty.Register("TotalItemCount", typeof(int), typeof(ComboBoxPageable), new PropertyMetadata(0, new PropertyChangedCallback(TotalItemCountChanged)));
|
|
|
|
private static void TotalItemCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
|
|
try
|
|
{
|
|
if (!(d is ComboBoxPageable me))
|
|
return;
|
|
|
|
me.pageCount = me.TotalItemCount % itemsPerPage == 0 ? me.TotalItemCount / itemsPerPage : (me.TotalItemCount / itemsPerPage) + 1;
|
|
me.UpdatePageTracker();
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
|
|
"SelectedItem",
|
|
typeof(object),
|
|
typeof(ComboBoxPageable),
|
|
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
|
|
|
|
public object SelectedItem
|
|
{
|
|
get { return GetValue(SelectedItemProperty); }
|
|
set { SetValue(SelectedItemProperty, value); }
|
|
}
|
|
|
|
#region SearchDataChanged
|
|
|
|
public EventHandler<cF4sdHealthSelectionDataRequest> SearchDataChanged
|
|
{
|
|
get { return (EventHandler<cF4sdHealthSelectionDataRequest>)GetValue(SearchDataChangedProperty); }
|
|
set { SetValue(SearchDataChangedProperty, value); }
|
|
}
|
|
|
|
|
|
public static readonly DependencyProperty SearchDataChangedProperty =
|
|
DependencyProperty.Register("SearchDataChanged", typeof(EventHandler<cF4sdHealthSelectionDataRequest>), typeof(ComboBoxPageable), new PropertyMetadata(null));
|
|
|
|
#endregion
|
|
|
|
#region ItemData
|
|
|
|
public ObservableCollection<KeyValuePair<string, object>> ItemData
|
|
{
|
|
get { return (ObservableCollection<KeyValuePair<string, object>>)GetValue(ItemDataProperty); }
|
|
set
|
|
{
|
|
SetValue(ItemDataProperty, value);
|
|
}
|
|
}
|
|
|
|
public static readonly DependencyProperty ItemDataProperty =
|
|
DependencyProperty.Register("ItemData", typeof(ObservableCollection<KeyValuePair<string, object>>), typeof(ComboBoxPageable), new PropertyMetadata(null));
|
|
|
|
#endregion
|
|
|
|
#region Styles
|
|
|
|
public Brush ComboBoxBackground
|
|
{
|
|
get { return (Brush)GetValue(ComboBoxBackgroundProperty); }
|
|
set { SetValue(ComboBoxBackgroundProperty, value); }
|
|
}
|
|
|
|
public static readonly DependencyProperty ComboBoxBackgroundProperty =
|
|
DependencyProperty.Register("ComboBoxBackground", typeof(Brush), typeof(ComboBoxPageable), new PropertyMetadata(Brushes.Transparent));
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
public ComboBoxPageable()
|
|
{
|
|
InitializeComponent();
|
|
timer.Elapsed += TimerElapsed;
|
|
}
|
|
|
|
private void TimerElapsed(object sender, ElapsedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
timer.Stop();
|
|
Dispatcher.Invoke(InvokeSearchValueChanged);
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
}
|
|
private void InvokeSearchValueChanged()
|
|
{
|
|
try
|
|
{
|
|
searchData.Page = pageIndex;
|
|
|
|
if (SearchDataChanged != null)
|
|
SearchDataChanged.Invoke(this, searchData);
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
}
|
|
|
|
public KeyValuePair<string, object>? GetSelectedValue()
|
|
{
|
|
try
|
|
{
|
|
if (ComboBoxControl.SelectedItem is KeyValuePair<string, object> selectedItem)
|
|
return selectedItem;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
#region Paging Events
|
|
|
|
#region PageBack
|
|
|
|
private void PageBackButton_Click(RoutedEventArgs e)
|
|
{
|
|
if (pageIndex <= 0)
|
|
{
|
|
e.Handled = true;
|
|
return;
|
|
}
|
|
pageIndex--;
|
|
InvokeSearchValueChanged();
|
|
UpdatePageTracker();
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void PageBackButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
|
{
|
|
PageBackButton_Click(e);
|
|
}
|
|
|
|
private void PageBackButton_TouchDown(object sender, TouchEventArgs e)
|
|
{
|
|
PageBackButton_Click(e);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region PageFor
|
|
|
|
private void PageForButton_Click(RoutedEventArgs e)
|
|
{
|
|
if (pageIndex + 1 >= pageCount)
|
|
return;
|
|
|
|
pageIndex++;
|
|
InvokeSearchValueChanged();
|
|
UpdatePageTracker();
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void PageForButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
|
{
|
|
PageForButton_Click(e);
|
|
}
|
|
|
|
private void PageForButton_TouchDown(object sender, TouchEventArgs e)
|
|
{
|
|
PageForButton_Click(e);
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
private void UpdatePageTracker()
|
|
{
|
|
try
|
|
{
|
|
var pageTrackerElement = ComboBoxControl.Template.FindName("PageTrackerTextBlock", ComboBoxControl);
|
|
|
|
if (!(pageTrackerElement is TextBlock pageTrackerTextBlock))
|
|
return;
|
|
|
|
pageTrackerTextBlock.Text = $"{pageIndex + 1} / {pageCount}";
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
}
|
|
|
|
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (!(sender is TextBox searchTextBox))
|
|
return;
|
|
|
|
pageIndex = 0;
|
|
searchData.Search = searchTextBox.Text;
|
|
UpdatePageTracker();
|
|
|
|
timer.Stop();
|
|
timer.Start();
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
}
|
|
|
|
private void ComboBoxControl_DropDownClosed(object sender, EventArgs e)
|
|
{
|
|
timer.Stop();
|
|
cFocusInvoker.InvokeLostFocus(this, e);
|
|
}
|
|
|
|
private void ComboBoxControl_DropDownOpened(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
// Elterninfo nur setzen, wenn (noch) nicht sinnvoll vorhanden
|
|
bool invalidIndex = false;
|
|
if (ParentElement is Panel p && (ParentIndex == null || ParentIndex < 0 || ParentIndex > p.Children.Count))
|
|
invalidIndex = true;
|
|
|
|
if (ParentElement == null || invalidIndex)
|
|
{
|
|
ParentElement = this.Parent as UIElement;
|
|
|
|
if (this.Parent is Panel panel)
|
|
ParentIndex = panel.Children.IndexOf(this);
|
|
else
|
|
ParentIndex = null;
|
|
}
|
|
|
|
|
|
cFocusInvoker.InvokeGotFocus(this, e);
|
|
InvokeSearchValueChanged();
|
|
|
|
|
|
#region Focus auf Textfeld setzen beim Öffnen der Combobox
|
|
if (!(sender is ComboBox comboBox)) return;
|
|
|
|
// Zugriff auf das Popup-Element
|
|
Popup partPopup = comboBox.Template.FindName("PART_Popup", comboBox) as Popup;
|
|
if (partPopup == null) return;
|
|
|
|
// Verzögerter Fokus
|
|
var _h = Dispatcher.BeginInvoke((Action)(() =>
|
|
{
|
|
if (partPopup.IsOpen)
|
|
{
|
|
// Suchen des SearchTextBox-Element innerhalb des Popups
|
|
TextBox searchTextBox = FindVisualChild<TextBox>(partPopup.Child, "SearchTextBox");
|
|
if (searchTextBox != null)
|
|
{
|
|
// Setzen des Fokus auf TextBox
|
|
searchTextBox.Focus();
|
|
}
|
|
}
|
|
}), System.Windows.Threading.DispatcherPriority.Loaded);
|
|
#endregion
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
}
|
|
|
|
private static T FindVisualChild<T>(DependencyObject parent, string childName) where T : DependencyObject
|
|
{
|
|
if (parent == null) return null;
|
|
|
|
T foundChild = null;
|
|
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
|
|
|
|
for (int i = 0; i < childrenCount; i++)
|
|
{
|
|
var child = VisualTreeHelper.GetChild(parent, i);
|
|
var childType = child as T;
|
|
if (childType == null)
|
|
{
|
|
foundChild = FindVisualChild<T>(child, childName);
|
|
if (foundChild != null) break;
|
|
}
|
|
else if (!string.IsNullOrEmpty(childName))
|
|
{
|
|
var frameworkElement = child as FrameworkElement;
|
|
if (frameworkElement != null && frameworkElement.Name == childName)
|
|
{
|
|
return (T)child;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return (T)child;
|
|
}
|
|
}
|
|
return foundChild;
|
|
}
|
|
}
|
|
}
|