Search code examples
c#xamlmvvmbindingdatacontext

My MVVM pattern is not working... Why?


in this example I try to develop a simple tool to manage software licenses for customers. It is implemented in C# WPF and the central design pattern is based on the MVVM paradigm (seperation of presentation and logic/data layer with INotifyPropertyChanged, ICommand and other stuff).

Why is the dynamical binding of properties in XAML not possible? Please look at the attached links at the end for more information.

Thank you for your help!

Felix

Relevant part of my view (XAML):

<DataGrid ItemsScource="{Binding Licenses}" SelectedItem="{Binding SelectedLicense}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding CustomerConverted}" Header="Customer"/>
                <DataGridTextColumn Binding="{Binding LicenseNoConverted}" Header="License no."/>
                <DataGridTextColumn Binding="{Binding LicenseKey}" Header="License key"/>
                <DataGridTextColumn Binding="{Binding LastActivation}" Header="Last activated ver."/>
                <DataGridTextColumn Binding="{Binding TypeConverted}"/>
            </DataGrid.Columns>
        </DataGrid> 

Codebehind

public partial class WMain : Window {
    public WMain() { 
        InitializeComponent();

        //construct ViewModel (works fine, all properties are consistent)
        WMainCtrl ctrl = new WMainCtrl(); 

        //set data context in code behind (XAML-bindings are not working)
        this.DataContext = ctrl;

        //that works instead... why?
        //c_dgLicenses.ItemsSource = ctrl.Licenses;        
    }
}

ViewModel:

public class WMainCtrl : BaseCtrl {

    public WMainCtrl() {
        try {
            //init data
            License.selectAndConvertData();
        } catch (Exception exc) {
            throw exc;
        }
    }

    //this works, the collection is definitely filled 
    internal ObservableCollection<License> Licenses { get { return License.Obscol; } }

    private License _selectedLicense;
    public License SelectedLicense {
        get {
            if (_selectedLicense == null) {
                if (Licenses.Count == 0) {
                    return null;
                }
                return Licenses[0];
            } else
            return _selectedLicense;
        }
        set {
            if (_selectedLicense != value) {
                _selectedLicense = value;
                try {
                    Console.WriteLine(SelectedLicense.LicenseKey);
                } catch (Exception) {}
                OnPropertyChanged();
            }
        }
    }
}

Relevant part of ViewModelBase:

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null) {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;

Here are some detail information:

Architecture (rough draft, no UML rules)

Screenshot: DataContext is set properly?!


Solution

  • My old ViewModel property (not working)

    internal ObservableCollection<License> Licenses { get { return License.Obscol; } }
    

    My new ViewModel property (working)

    public ObservableCollection<License> Licenses { get { return License.Obscol; } }