<local:LookUpGridColumn x:Name="colInvoiceSelect" FieldName="InvoiceSurcharge" Header="Invoice" Width="120" ReadOnly="false" AllowEditing="true"/> colInvoiceSelect.SetOptions<CreditorInvoiceClient>(invoiceItemSource);
<dxg:GridColumn x:Class="Views.Controls.LookUpGridColumn"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:controls="clr-namespace:Views.Controls"
x:Name="myColumn"
>
<dxg:GridColumn.Resources>
<controls:DisplayTextConverter x:Key="DisplayTextConverter"/>
</dxg:GridColumn.Resources>
<dxg:GridColumn.EditSettings>
<dxg:LookUpEditSettings x:Name="LookupCombo" ValueMember="KeyStr" DisplayMember="KeyName" AutoPopulateColumns="False" FindMode="Always" FilterCondition="Contains" ImmediatePopup="True"
IsCaseSensitiveFilter="False"
PopupWidth="600"
ShowPopupIfReadOnly="False"
ItemsSource="{Binding ElementName=myColumn,Path=LookupItems}"
>
<dxg:LookUpEditSettings.StyleSettings>
<dxg:SearchLookUpEditStyleSettings AllowGrouping="False"/>
</dxg:LookUpEditSettings.StyleSettings>
<dxg:LookUpEditSettings.PopupContentTemplate>
<ControlTemplate>
<dxg:GridControl Name="PART_GridControl">
<dxg:GridControl.Columns>
<dxg:GridColumn FieldName="KeyStr" Header="{Binding Converter={StaticResource GlobalLocalizationValueConverter},ConverterParameter=Key}" Width="150"/>
<dxg:GridColumn FieldName="KeyName" Header="{Binding Converter={StaticResource GlobalLocalizationValueConverter},ConverterParameter=ItemName}" Width="400" />
</dxg:GridControl.Columns>
<dxg:GridControl.View>
<dxg:TableView AutoWidth="False" SearchStringToFilterCriteria="CurrentTableView_SearchStringToFilterCriteria" SearchPanelHighlightResults="True" SearchDelay="50" x:Name="CurrentTableView"/>
</dxg:GridControl.View>
</dxg:GridControl>
</ControlTemplate>
</dxg:LookUpEditSettings.PopupContentTemplate>
</dxg:LookUpEditSettings>
</dxg:GridColumn.EditSettings>
</dxg:GridColumn>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Windows.Data;
using DevExpress.Data.Filtering;
using DevExpress.Xpf.Grid;
using ViewModels.Models;
using Uniconta.API.System;
using Uniconta.Common;
namespace Views.Controls
{
public partial class LookUpGridColumn : GridColumn
{
public LookUpGridColumn() : base()
{
Loaded += LookUpGridColumn_Loaded;
InitializeComponent();
}
public delegate CriteriaOperator FilterHandler(object row);
public FilterHandler OnFilter { get; set; }
public delegate void ChangeHandler(object row, string fieldName, object value, string text);
public ChangeHandler OnChange { get; set; }
private void LookUpGridColumn_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
if (View is TableView tableView)
{
tableView.EditorShowMode = DevExpress.Xpf.Core.EditorShowMode.MouseDown;
tableView.CellValueChanged += TableView_CellValueChanged;
if (tableView.Parent is GridControl grid)
{
grid.CurrentColumnChanged += Grid_CurrentColumnChanged;
grid.CurrentItemChanged += Grid_CurrentItemChanged;
}
}
}
private void TableView_CellValueChanged(object sender, CellValueChangedEventArgs e)
{
OnChange?.Invoke(e.Row, e.Column.FieldName, e.Value, GetText(e.Value));
}
public ObservableCollection<object> LookupItems { get; set; } = new ObservableCollection<object>();
public bool SelectionOnCurrenColum { get; private set; }
public bool SearchAlsoInKey = true;
private object currentRow;
private List<IdKey> items;
public void InitControl<T>(CrudAPI api, bool searchAlsoInKey = true) where T : class, UnicontaBaseEntity, IdKey, new()
{
SetOptions<T>(api.LoadCache<T>().Result);
this.SearchAlsoInKey = searchAlsoInKey;
}
public void SetOptions<T>(IEnumerable<IdKey> options) where T : UnicontaBaseEntity
{
items = options.Select((x, i) => new SimpleIdKey<T>((T)x, x.KeyStr, x.KeyName, i)).Cast<IdKey>().ToList();
LookupItems.Clear();
items.ForEach(i => LookupItems.Add(i));
var displayTextConverter = new DisplayTextConverter(GetText);
this.LookupCombo.DisplayTextConverter = displayTextConverter;
}
public string GetText(object key)
{
if (key == null)
return null;
return items.FirstOrDefault(x => x.KeyStr == key.ToString())?.KeyName;
}
private void Grid_CurrentItemChanged(object sender, CurrentItemChangedEventArgs e)
{
currentRow = e.NewItem;
SetFilter();
}
private void SetFilter()
{
if (SelectionOnCurrenColum)
{
LookupCombo.FilterCriteria = OnFilter?.Invoke(currentRow) ?? null;
}
}
private void Grid_CurrentColumnChanged(object sender, CurrentColumnChangedEventArgs e)
{
SelectionOnCurrenColum = (e.NewColumn == this);
currentRow = e.Source?.CurrentItem;
SetFilter();
}
private void CurrentTableView_SearchStringToFilterCriteria(object sender, SearchStringToFilterCriteriaEventArgs e)
{
if (e.SearchString != null)
{
CriteriaOperator filter = null;
var columns = new List<string> { "KeyName" };
if (SearchAlsoInKey)
columns.Add("KeyStr");
columns.ForEach(c =>
{
filter |= CriteriaOperator.Or(
CriteriaOperator.Parse(string.Format("Contains([{0}], '{1}')", c, e.SearchString)),
CriteriaOperator.Parse(string.Format("Contains([{0}], '{1}')", c, e.SearchString.Replace(".", ","))),
CriteriaOperator.Parse(string.Format("Contains([{0}], '{1}')", c, e.SearchString.Replace("*", "x"))),
CriteriaOperator.Parse(string.Format("Contains([{0}], '{1}')", c, e.SearchString.Replace(".", ",").Replace("*", "x")))
);
});
e.Filter = filter;
}
}
}
public class DisplayTextConverter : IValueConverter
{
public delegate string KeyToTextHandler(object key);
public KeyToTextHandler Converter;
public DisplayTextConverter(KeyToTextHandler converter)
{
Converter = converter;
}
public DisplayTextConverter()
{
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => Converter(value);
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) => value;
}
}
Extended
<dxg:GridColumn x:Class="Views.Controls.ExtendedLookUpGridColumn"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:controls="clr-namespace:Views.Controls"
x:Name="myColumn"
>
<dxg:GridColumn.Resources>
<controls:DisplayTextConverter x:Key="DisplayTextConverter"/>
</dxg:GridColumn.Resources>
<dxg:GridColumn.EditSettings>
<dxg:LookUpEditSettings x:Name="LookupCombo" ValueMember="KeyStr" DisplayMember="KeyName" AutoPopulateColumns="False" FindMode="Always" FilterCondition="Contains" ImmediatePopup="True"
IsCaseSensitiveFilter="False"
PopupWidth="600"
ShowPopupIfReadOnly="False"
ItemsSource="{Binding ElementName=myColumn,Path=LookupItems}"
>
<dxg:LookUpEditSettings.StyleSettings>
<dxg:SearchLookUpEditStyleSettings AllowGrouping="False"/>
</dxg:LookUpEditSettings.StyleSettings>
<dxg:LookUpEditSettings.PopupContentTemplate>
<ControlTemplate>
<dxg:GridControl Name="PART_GridControl" ColumnsSource="{Binding ElementName=myColumn,Path=PopupColumns}" AutoGenerateColumns="None">
<!--<dxg:GridControl.Columns>
<dxg:GridColumn FieldName="KeyStr" Header="{Binding Converter={StaticResource GlobalLocalizationValueConverter}, ConverterParameter=Key}" Width="150"/>
<dxg:GridColumn FieldName="KeyName" Header="{Binding Converter={StaticResource GlobalLocalizationValueConverter}, ConverterParameter=Description}" Width="400" />
</dxg:GridControl.Columns>-->
<dxg:GridControl.View>
<dxg:TableView AutoWidth="False" SearchStringToFilterCriteria="CurrentTableView_SearchStringToFilterCriteria" SearchPanelHighlightResults="True" SearchDelay="50" x:Name="CurrentTableView"/>
</dxg:GridControl.View>
</dxg:GridControl>
</ControlTemplate>
</dxg:LookUpEditSettings.PopupContentTemplate>
</dxg:LookUpEditSettings>
</dxg:GridColumn.EditSettings>
</dxg:GridColumn>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using DevExpress.Data.Filtering;
using DevExpress.Xpf.Grid;
namespace Views.Controls
{
public partial class ExtendedLookUpGridColumn : GridColumn
{
public ExtendedLookUpGridColumn() : base()
{
Loaded += LookUpGridColumn_Loaded;
InitializeComponent();
}
public delegate CriteriaOperator FilterHandler(object row);
public FilterHandler OnFilter { get; set; }
public delegate void ChangeHandler(object row, string fieldName, object value, string text);
public event ChangeHandler OnChange;
private void LookUpGridColumn_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
if (View is TableView tableView)
{
tableView.EditorShowMode = DevExpress.Xpf.Core.EditorShowMode.MouseDown;
tableView.CellValueChanged += TableView_CellValueChanged;
if (tableView.Parent is GridControl grid)
{
grid.CurrentColumnChanged += Grid_CurrentColumnChanged;
grid.CurrentItemChanged += Grid_CurrentItemChanged;
}
}
}
private void TableView_CellValueChanged(object sender, CellValueChangedEventArgs e)
{
OnChange?.Invoke(e.Row, e.Column.FieldName, e.Value, GetText(e.Value));
}
public ObservableCollection<GridColumn> PopupColumns { get; set; } = new ObservableCollection<GridColumn>();
public void SetColumns(IEnumerable<GridColumn> columns)
{
PopupColumns.Clear();
foreach (var column in columns)
PopupColumns.Add(column);
}
private ILookupDataSource DataSource;
public ObservableCollection<object> LookupItems { get; set; } = new ObservableCollection<object>();
public bool SelectionOnCurrenColum { get; private set; }
private object currentRow;
public void SetOptions<T>(IEnumerable<T> options, Func<T, string> keySelector, Func<T, string> nameSelector) where T : class
{
DataSource = new LookupDataSource<T>(keySelector, nameSelector, options);
LookupItems.Clear();
foreach (var option in options)
{
LookupItems.Add(option);
}
LookupCombo.DisplayTextConverter = new DisplayTextConverter(GetText);
}
public string GetText(object key)
{
if (key == null)
return null;
var itemByKey = DataSource.Items.Select(x => new { Key = DataSource.GetKey(x), Name = DataSource.GetName(x) }).ToList();
var item = itemByKey.FirstOrDefault(x => x.Key?.ToString() == key?.ToString());
if (item == null) return "";
return item.Name;
}
private void Grid_CurrentItemChanged(object sender, CurrentItemChangedEventArgs e)
{
currentRow = e.NewItem;
SetFilter();
}
private void SetFilter()
{
if (SelectionOnCurrenColum)
{
LookupCombo.FilterCriteria = OnFilter?.Invoke(currentRow) ?? null;
}
}
private void Grid_CurrentColumnChanged(object sender, CurrentColumnChangedEventArgs e)
{
SelectionOnCurrenColum = (e.NewColumn == this);
currentRow = e.Source?.CurrentItem;
SetFilter();
}
private void CurrentTableView_SearchStringToFilterCriteria(object sender, SearchStringToFilterCriteriaEventArgs e)
{
if (e.SearchString != null && PopupColumns != null)
{
CriteriaOperator filter = null;
var columns = PopupColumns.Select(x => x.FieldName).ToList();
columns.ForEach(c =>
{
filter |= CriteriaOperator.Or(
CriteriaOperator.Parse(string.Format("Contains([{0}], '{1}')", c, e.SearchString)),
CriteriaOperator.Parse(string.Format("Contains([{0}], '{1}')", c, e.SearchString.Replace(".", ","))),
CriteriaOperator.Parse(string.Format("Contains([{0}], '{1}')", c, e.SearchString.Replace("*", "x"))),
CriteriaOperator.Parse(string.Format("Contains([{0}], '{1}')", c, e.SearchString.Replace(".", ",").Replace("*", "x")))
);
});
e.Filter = filter;
}
}
}
public interface ILookupDataSource
{
ObservableCollection<object> Items { get; }
object GetKey(object o);
string GetName(object o);
}
public class LookupDataSource<T> : ILookupDataSource where T : class
{
Func<T, object> keySelector;
Func<T, string> nameSelector;
public LookupDataSource(Func<T, object> keySelector, Func<T, string> nameSelector, IEnumerable<T> items)
{
this.keySelector = keySelector;
this.nameSelector = nameSelector;
Items = new ObservableCollection<object>(items);
}
public ObservableCollection<object> Items { get; private set; }
object ILookupDataSource.GetKey(object o) => o is T v ? keySelector(v) : null;
string ILookupDataSource.GetName(object o) => o is T v ? nameSelector(v) : "";
}
}
1009500cookie-checkXAML / Uniconta LookupGridColumn