First, thank you for this great project! Please consider my pull request that I will submit shortly, which aims to help with the following.
Problem #1: in a datatable I would like to add a button that, when clicked, shows the pop-up filter attached to one of the columns and pre-populates the values. This is useful because it is then possible to create specific filters easily in code, while at the same time showing to the user how this filter is created by opening the filter pop-up.
Problem #2: I would also like easier access to certain properties of this custom filter control without having to wire together the popup control, the DataGridFilterColumnControl, and the DataGridFilterColumn through binding as you have done for example with the Filter property,
I will create a pull request that implements this and adds two buttons to the "Customized 2" tab of the demo app.
Implementation of button #1, "Open & Populate a Filter"
Setting values for the Min and Max values is possible and trivial with the existing code. A new "Column5Filter" property is added to Customized2ViewModel and the DataGridFilterColumn.Filter attached property is bound to it in xaml with dgx:DataGridFilterColumn.Filter="{Binding Column5Filter}"
It is then possible to do Column5Filter = new ContentFilter(0.5d, 1d);
in the DelegateCommand bound to the button. For this nothing had to be changed in the DataGridExtensions project.
In order to control the visibility of the pop-up when the button is pressed, I added an IsPopupVisible
attached property to DataGridFilterColumn, and another dependency property with the same name to DataGridFilterColumnControl, as well as to FilterWithPopupControl, and I also added a Column5PopupVisible
property to the Customized2ViewModel, and bound them all to each other much like how the Filter
property is implemented in the original code. Now it's possible to do Column5PopupVisible = true;
in the DelegateCommand bound to the button to show the pop-up. I did not consider this bad practice because "IsPopupVisible" may well apply to many custom filter controls, so it should be widespread enough to warrant having such a property on DataGridFilterColumn itself. After a bit of debugging and fixes this works fine.
Implementation of button #2, "Change Popup Caption"
Making all the required changes for the IsPopupVisible
property to be usable was difficult and time-consuming. Of course, I am not familiar with the project. In any case, it also required changes to be made to files in the DataGridExtensions project itself, which most users may not want to do (since that would put them on a fork of the project). Additionally, a user may create various types of custom filter controls with various properties, where it really wouldn't make sense to also create corresponding properties on the DataGridFilterColumnControl and the DataGridFilterColumn classes. Therefore I also made the following changes.
I defined a DataGridFilterColumnControl
attached property in DataGridFilterColumn, and updated the AttachColumnControl method in DataGridFilterHost to inject the filterColumnControl into this property:
public sealed class DataGridFilterHost {
...
internal void AttachColumnControl(DataGridColumn column, DataGridFilterColumnControl filterColumnControl)
{
column.SetFilterHost(this);
column.SetDataGridFilterColumnControl(filterColumnControl); <-- New line
...
I also created a FilterControl property on DataGridFilterColumnControl, and overrode OnApplyTemplate() so as to set the FilterControl to the actual control generated after the control is drawn:
public class DataGridFilterColumnControl {
...
/// <summary>
/// The actual filter control generated at runtime.
/// </summary>
public Control? FilterControl
{
get;
set;
}
/// <summary>
/// Populate the FilterControl property once the template is applied.
/// </summary>
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (VisualTreeHelper.GetChildrenCount(this) == 1
&& VisualTreeHelper.GetChild(this, 0) is Control filterControl)
{
FilterControl = filterControl;
}
}
This way it becomes possible to do as follows in code:
var dataGridFilterColumnControl = DataGridFilterColumn.GetDataGridFilterColumnControl(dataGridColumn);
if (dataGridFilterColumnControl.FilterControl is IntegerDynamicDualValueFilter integerDynamicDualValueFilter) {
...
In the above code IntegerDynamicDualValueFilter is a custom filter control in my own project, but it could be any filter control class you've created.
In the sample project I did as follows in order to easily be able to set the caption of the "FilterWithPopupControl" control:
- I created a
Caption
property on the FilterWithPopupControl: public string Caption...
- I bound the corresponding textbox to this property:
<TextBlock x:Name="Caption" Text="{Binding Path=Caption, ElementName=Control, TargetNullValue='Enter the limits:'}" Margin="0,3" />
- I created a property in the viewmodel to be able to access the FilterColumnControl:
public DataGridFilterColumnControl Column5FilterColumnControl { get; set; }
- Bound this property in xaml:
BindingOperations.SetBinding(Column5, DataGridFilterColumn.DataGridFilterColumnControlProperty, new Binding("DataContext.Column5FilterColumnControl") { Source = this, Mode = BindingMode.TwoWay });
It then became possible to do as follows in order to set the caption of the popup dialog:
class Customized2ViewModel : ObservableObject {
...
public ICommand ProgrammaticAccessToFilterControlCommand => new DelegateCommand(ProgrammaticAccessToFilterControl);
private void ProgrammaticAccessToFilterControl()
{
if (Column5FilterColumnControl.FilterControl is FilterWithPopupControl filterWithPopupControl)
{
filterWithPopupControl.Caption = "New Popup Caption:";
Column5PopupVisible = true;
}
}
As you can see now it's possible to control various aspects of a custom filter control without making any changes in the core DataGridExtensions project, and without having to resort to ugly and slow static helper methods that traverse the visual tree. Yes, this is not optimal MVVM and may raise concerns regarding separation of the viewmodel and the view, but it works and makes such logic possible in the future without having to fork the DataGridExtensions project and without having to spend a day trying to understand how it works.
Thanks for considering my PR.