Click here to Skip to main content
15,888,454 members
Home / Discussions / WPF
   

WPF

 
PinnedHOW TO ANSWER A QUESTION PinPopular
Chris Maunder16-Jul-09 3:09
cofounderChris Maunder16-Jul-09 3:09 
PinnedHow to get an answer to your question PinPopular
Chris Maunder16-Jul-09 3:05
cofounderChris Maunder16-Jul-09 3:05 
QuestionBinding Header in TabItem to child property in the ViewModel Pin
Kenneth Haugland15hrs 36mins ago
mvaKenneth Haugland15hrs 36mins ago 
QuestionDataGrid Built In ViewModel Question Pin
Kevin Marois8-Apr-24 13:24
professionalKevin Marois8-Apr-24 13:24 
I'm building and populating a DataGrid in a viewmodel.

Here's what I'm making[^]

The two columns on the right, AutoAdjustment and AutoPosting, are combo boxes where the user can selecte 'Y' or 'N'. These are the only editable columns.

For my source data, I have a list of objects called ProcoessingOutputEntries, each with a list of column objects. It's basically a 'row' object with a dynamic collection of columns on it:
private List<ProcessingOutputEntryEntity> _ProcesssingOutputEntries;
public List<ProcessingOutputEntryEntity> ProcesssingOutputEntries
{
    get { return _ProcesssingOutputEntries; }
    set
    {
        if (_ProcesssingOutputEntries != value)

        {
            _ProcesssingOutputEntries = value;
            RaisePropertyChanged(nameof(ProcesssingOutputEntries));
        }
    }
}
and
public class ProcessingOutputEntryEntity : _EntityBase
{
    private List<ColumnInfoEntity> _ProcesssingOutputColumns;
    public List<ColumnInfoEntity> ProcesssingOutputColumns
    {
        get { return _ProcesssingOutputColumns; }
        set
        {
            if (_ProcesssingOutputColumns != value)
            {
                _ProcesssingOutputColumns = value;
                RaisePropertyChanged(nameof(ProcesssingOutputColumns));
            }
        }
    }
}
and
public class ColumnInfoEntity : _EntityBase
{
    private string _ColumnName;
    public string ColumnName
    {
        get { return _ColumnName; }
        set
        {
            if (_ColumnName != value)
            {
                _ColumnName = value;
                RaisePropertyChanged(nameof(ColumnName));
            }
        }
    }

    private ColumnSources _ColumnSource;
    public ColumnSources ColumnSource
    {
        get { return _ColumnSource; }
        set
        {
            if (_ColumnSource != value)
            {
                _ColumnSource = value;
                RaisePropertyChanged(nameof(ColumnSource));
            }
        }
    }

    private ColumnTypes _ColumnType;
    public ColumnTypes ColumnType
    {
        get { return _ColumnType; }
        set
        {
            if (_ColumnType != value)
            {
                _ColumnType = value;
                RaisePropertyChanged(nameof(ColumnType));
            }
        }
    }

    private int _ColumnWidth;
    public int ColumnWidth
    {
        get { return _ColumnWidth; }
        set
        {
            if (_ColumnWidth != value)
            {
                _ColumnWidth = value;
                RaisePropertyChanged(nameof(ColumnWidth));
            }
        }
    }

    private string _DisplayAs;
    public string DisplayAs
    {
        get { return _DisplayAs; }
        set
        {
            if (_DisplayAs != value)
            {
                _DisplayAs = value;
                RaisePropertyChanged(nameof(DisplayAs));
            }
        }
    }

    private int _IndexPosition;
    public int IndexPosition
    {
        get { return _IndexPosition; }
        set
        {
            if (_IndexPosition != value)
            {
                _IndexPosition = value;
                RaisePropertyChanged(nameof(IndexPosition));
            }
        }
    }

    private bool _IsUserEditable = true;
    public bool IsUserEditable
    {
        get { return _IsUserEditable; }
        set
        {
            if (_IsUserEditable != value)
            {
                _IsUserEditable = value;
                RaisePropertyChanged(nameof(IsUserEditable));
            }
        }
    }

    private object _Data;
    public object Data
    {
        get { return _Data; }
        set
        {
            if (_Data != value)
            {
                _Data = value;
                RaisePropertyChanged(nameof(Data));
            }
        }
    }

    public override string ToString()
    {
        return $"{ColumnSource} {IndexPosition} {ColumnName}";
    }
}
I handle the WindowLoaded event to create the grid in my ViewModel:
private void WindowLoadedExecuted()
{
    // At this point, the row objects don't have an Id, so create one for each row.
    _results.ProcesssingOutputEntries.ForEach(x => x.Id = Guid.NewGuid());

    // Now, add an Id column in front of all other columns
    foreach (var entry in _results.ProcesssingOutputEntries)
    {
        var col = new ColumnInfoEntity
        {
            ColumnName = "Id",
            Data = entry.Id.ToString()
        };

        entry.ProcesssingOutputColumns.Insert(0, col);
    }

    DataColumn column = null;

    // Add data table columns using the column info objects on the first processing object
    var firstEntry = _results.ProcesssingOutputEntries.FirstOrDefault();
    foreach (var col in firstEntry.ProcesssingOutputColumns)
    {
        column = new DataColumn
        {
            DataType = Type.GetType("System.String"),
            ReadOnly = false
        };
        ColumnsDataTable.Columns.Add(column);
    }

    // Get the index positions of the AutoAdjustment and AutoPosting columns, so we can make all
    // other columns read-only
    var autoAdjColIndex = -1;
    var autoPostColIndex = -1;

    var autoAdjCol = GetProcessingOutputColumn(ColumnTypes.AutoAdjustment);

    if(autoAdjCol != null)
    {
        autoAdjColIndex = firstEntry.ProcesssingOutputColumns.IndexOf(autoAdjCol);
    }

    var autoPostCol = GetProcessingOutputColumn(ColumnTypes.AutoPosting);

    if (autoPostCol != null)
    {
        autoPostColIndex = firstEntry.ProcesssingOutputColumns.IndexOf(autoPostCol);
    }

    // Get a list of column names from the data table created above
    string[] columnNames = (from dc in ColumnsDataTable.Columns.Cast()
                            select dc.ColumnName).ToArray();

    // Create styles for the cells
    var textBoxStyle = new Style();
    textBoxStyle.Setters.Add(new Setter(TextBox.TextAlignmentProperty, TextAlignment.Right));

    var comboBoxStyle = new Style();
    comboBoxStyle.Setters.Add(new EventSetter(ComboBox.SelectionChangedEvent, new SelectionChangedEventHandler(ComboSelectionChanged)));

    // Go through each column
    int index = 0;
    foreach (string columnName in columnNames)
    {
        // Create binding
        var binding = new Binding(columnName);

        // If the column is the AutoAdjustment or AutoPosting column, add combo box columns
        // These two columns will be the right most two
        if (index == autoAdjColIndex || index == autoPostColIndex)
        {
            // Add a combo box column for it
            var col = new DataGridComboBoxColumn()
            {
                Header = firstEntry.ProcesssingOutputColumns[index].ColumnName,
                ItemsSource = new List { "Y", "N" },
                Visibility = Visibility.Visible,
                TextBinding = binding,
                IsReadOnly = false,
                CellStyle = comboBoxStyle,<br />
            };
            DataGridColumns.Add(col);
        }
        else
        {
            // Otherwise, add a read-only textbox column for it
            var col = new DataGridTextColumn()
            {
                Header = firstEntry.ProcesssingOutputColumns[index].ColumnName,
                Binding = binding,
                Visibility = Visibility.Visible,
                IsReadOnly = true,
                CellStyle = textBoxStyle
            };
            DataGridColumns.Add(col);
        }

        index++;
    }

    // Hide the first column, the Id
    //DataGridColumns.FirstOrDefault().Visibility = Visibility.Hidden;

    // Load the data into the grid
    LoadData();
}
Here's how the data is loaded
private void LoadData()
{
    ColumnsDataTable.Clear();

    foreach (var processingEntry in _results.ProcesssingOutputEntries)
    {
        // Create a new row
        DataRow row = ColumnsDataTable.NewRow();
        ColumnsDataTable.Rows.Add(row);

        // Add each column's data
        var index = 0;
        foreach (var col in processingEntry.ProcesssingOutputColumns)
        {
            row[index] = col.Data;
            index++;
        }
    }
}
The ComboBox column style handles the SelectionChanged event:
var comboBoxStyle = new Style();
comboBoxStyle.Setters.Add(new EventSetter(ComboBox.SelectionChangedEvent, new SelectionChangedEventHandler(ComboSelectionChanged)));
and
private void ComboSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // Find the selected row
    var comboBox = e.Source as ComboBox;
    var dataGrid = WPFTools.GetVisualParent(comboBox);
    var dataRowView = dataGrid.SelectedItem as DataRowView;

    if(dataRowView != null)
    {
        // Get the new selection from the combo box. It will be either 'Y' or 'N'
        var newSelection = e.AddedItems[0];

        // Get the row's Id
        var rowId = dataRowView.Row[0].ToString();
    }
}

So, the question is, in this event handler, how do I set the newly selected value back to the source row? It seems like I need to get the row, then the bound object from it. But how do I know which combox fired this event?

Thanks
In theory, theory and practice are the same. But in practice, they never are.”
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.


modified 8-Apr-24 20:10pm.

AnswerRe: DataGrid Built In ViewModel Question Pin
Mycroft Holmes10-Apr-24 12:04
professionalMycroft Holmes10-Apr-24 12:04 
QuestionWPF .Net 6 Pin
Kevin Marois14-Mar-24 16:35
professionalKevin Marois14-Mar-24 16:35 
AnswerRe: WPF .Net 6 Pin
Pete O'Hanlon14-Mar-24 20:22
mvePete O'Hanlon14-Mar-24 20:22 
QuestionDependencyProperty fires only in ViewModel.ctor Pin
iwangoll25-Feb-24 7:34
iwangoll25-Feb-24 7:34 
AnswerRe: DependencyProperty fires only in ViewModel.ctor Pin
Richard Deeming25-Feb-24 22:44
mveRichard Deeming25-Feb-24 22:44 
GeneralRe: DependencyProperty fires only in ViewModel.ctor Pin
iwangoll26-Feb-24 1:51
iwangoll26-Feb-24 1:51 
GeneralRe: DependencyProperty fires only in ViewModel.ctor Pin
Richard Deeming26-Feb-24 2:19
mveRichard Deeming26-Feb-24 2:19 
GeneralRe: DependencyProperty fires only in ViewModel.ctor Pin
iwangoll26-Feb-24 3:16
iwangoll26-Feb-24 3:16 
QuestionGet Tab For Context Menu Pin
Kevin Marois26-Jan-24 18:35
professionalKevin Marois26-Jan-24 18:35 
QuestionINotifyDataErrorInfo Question Pin
Kevin Marois2-Jan-24 17:07
professionalKevin Marois2-Jan-24 17:07 
QuestionWhen Are All DependencyProperties Set Pin
Kevin Marois28-Dec-23 21:12
professionalKevin Marois28-Dec-23 21:12 
AnswerRe: When Are All DependencyProperties Set Pin
#realJSOP9-Apr-24 1:30
mve#realJSOP9-Apr-24 1:30 
QuestionDataTemplate Problem Pin
Kevin Marois5-Dec-23 12:08
professionalKevin Marois5-Dec-23 12:08 
AnswerRe: DataTemplate Problem Pin
Richard Deeming5-Dec-23 22:03
mveRichard Deeming5-Dec-23 22:03 
AnswerDataGrid Event Not Firing Pin
Kevin Marois30-Nov-23 13:11
professionalKevin Marois30-Nov-23 13:11 
GeneralRe: DataGrid Event Not Firing Pin
Andre Oosthuizen1-Dec-23 22:42
mveAndre Oosthuizen1-Dec-23 22:42 
GeneralRe: DataGrid Event Not Firing Pin
Kevin Marois2-Dec-23 7:41
professionalKevin Marois2-Dec-23 7:41 
QuestionDataGrid Exception Pin
Kevin Marois28-Nov-23 11:36
professionalKevin Marois28-Nov-23 11:36 
AnswerRe: DataGrid Exception Pin
Richard Deeming28-Nov-23 22:30
mveRichard Deeming28-Nov-23 22:30 
GeneralRe: DataGrid Exception Pin
Kevin Marois29-Nov-23 7:12
professionalKevin Marois29-Nov-23 7:12 
GeneralRe: DataGrid Exception Pin
Kevin Marois29-Nov-23 8:13
professionalKevin Marois29-Nov-23 8:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.