I'm always totally getting run over by these ComboBoxes. I'm thinking I understand them but it seems like I don't.
I wan't to be able to give an object a parent. So I've got this child object, it has a value that's a ID of the parent and I have a collection of parent items.
I select the Parent from the ComboBox and if I understand correctly it's ID property should be bound to the Child's ParentId property. It seems fine, when I select it the property goes over. The template is changed and it's displayed as a Textblock, all fine. when the template goes back into the ComboBox type suddenly it's Null. Shouldn't it find the comparable item in the collection where it's Id corresponds with ParentId ?
Here is the code:
PARENT
public class Parent
{
private string _id;
public string Id
{
get
{
return _id;
}
set
{
_id = value;
OnPropertyChanged("Id");
}
}
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged("Name");
}
}
}
CHILD
public class RulesMainClassViewModel : ViewModelBase
{
private string _id;
public string Id
{
get
{
return _id;
}
set
{
_id = value;
OnPropertyChanged("Id");
}
}
private string _parentId;
public string ParentId
{
get
{
return _parentId;
}
set
{
_parentId = value;
OnPropertyChanged("ParentId");
}
}
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged("Name");
}
}
}
XAML combobox
<ComboBox DisplayMemberPath="Name" SelectedValue="{Binding Path=ParentId, Mode=TwoWay}"
SelectedValuePath="Id" ItemsSource="{Binding Path=ParentCollection}" />
Not sure what your complete setting is like (and i can't really tell what's wrong with your code) but i tried to model something similar that has a common use, i made a ListView which binds to a collection of employees which have a Name and Occupation. The ComboBox has the purpose of changing the Occupation of the selected employee, the XAML for it looks like this:
<ComboBox ItemsSource="{Binding Occupations}"
SelectedValue="{Binding ElementName=lv,Path=SelectedItem.Occupation}"
SelectedValuePath="{Binding Occupation.Title}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
This seems to work. Note that my SelectedValuePath is a binding, maybe that is a problem...
(Class codes:)
public class Employee : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set { name = value;
NotifyPropertyChanged("Name");}
}
private Occupation occupation;
public Occupation Occupation
{
get { return occupation; }
set { occupation = value;
NotifyPropertyChanged("Occupation");}
}
public Employee(string name, Occupation occupation)
{
this.name = name;
this.occupation = occupation;
}
#region INotifyPropertyChanged Members
...
#endregion
}
public class Occupation : INotifyPropertyChanged
{
private string title;
public string Title
{
get { return title; }
set { title = value;
NotifyPropertyChanged("Title");}
}
public Occupation(string title)
{ Title = title; }
#region INotifyPropertyChanged Members
...
#endregion
}
Related
Problem Summary:
I'm having a bit of problem with my ListBox, it's unable to show the values of a collection it's bound to, which is weird because I've iterated through the collection and can confirm that they do have values. Also, I've bound another collection (which is contained within the same class as the first 1) to another ListBox and it works perfectly so the path I've set my bindings to does work as intended.
What I've done:
To try and figure out where this problem lies, I created a checklist of possible causes:
Does the observable collection have a value in the first place? Maybe
it's not showing anything because there's actually nothing in it?
Result: Passed - I created a command that MessageBox.Shows the content of the collection and it displayed the proper string value
Does the binding actually work? Maybe my DataContext is incorrect?
Maybe I'm in the wrong path/class?
Result: Passed - I have three ListBoxes:
ListBox(A) is bound to the ObservableCollection FirstName
ListBox(B) is bound to the ObservableCollection LastName
ListBox(C) is bound to the ObservableCollection All which only has a getter that combines the values of FirstName and LasName
They're all contained within the same class and both ListBox(A) and ListBox(B)'s bindings work so I'm certain that the path of my ListBox(C) is correct.
Does the collection get notified of changes?
Result: Passed - AFAIK ObservableCollections can automatically notify add/remove actions so I shouldn't have to implement it if those are only my requirements. I did implement it though since I want it to raise it on edits as well.
Unfortunately I can't seem to pinpoint the exact problem, does the ListBox have any problems with an IEnumerable that only has a get?
My Code:
I recreated a simple illustration of my implementation:
MainModel.cs
public class MainModel
{
public class Customer : INotifyImplementation
{
public Customer()
{
FirstName = "";
LastName = "";
}
private string firstName;
public string FirstName
{
get { return firstName; }
set { firstName = value;
RaisePropertyChanged("FirstName");
RaisePropertyChanged("FullName");
}
}
private string lastName;
public string LastName
{
get { return lastName; }
set { lastName = value;
RaisePropertyChanged("LastName");
RaisePropertyChanged("FullName");
}
}
public string FullName
{
get { return GetFullName(); }
}
public string GetFullName()
{
return FirstName + " " + LastName;
}
}
public class CustomerFieldErrors : INotifyImplementation
{
public CustomerFieldErrors()
{
FirstName = new ObservableCollection<string>();
LastName = new ObservableCollection<string>();
}
private ObservableCollection<string> firstName;
public ObservableCollection<string> FirstName
{
get { return firstName; }
set { firstName = value;
RaisePropertyChanged("FirstName");
RaisePropertyChanged("All");
}
}
private ObservableCollection<string> lastName;
public ObservableCollection<string> LastName
{
get { return lastName; }
set { lastName = value;
RaisePropertyChanged("LastName");
RaisePropertyChanged("All");
}
}
public ObservableCollection<string> All
{
get { return GetAllErrors(); }
}
public ObservableCollection<string> GetAllErrors()
{
ObservableCollection<string> allErrors = new ObservableCollection<string>();
foreach(string i in FirstName)
{
allErrors.Add(i);
}
foreach (string i in LastName)
{
allErrors.Add(i);
}
return allErrors;
}
}
public class CustomerFieldRestrictions : INotifyImplementation
{
public CustomerFieldRestrictions()
{
FirstName = new FieldRestrictions();
LastName = new FieldRestrictions();
}
private FieldRestrictions firstName;
public FieldRestrictions FirstName
{
get { return firstName; }
set { firstName = value; }
}
private FieldRestrictions lastName;
public FieldRestrictions LastName
{
get { return lastName; }
set { lastName = value; }
}
}
public class FieldRestrictions : INotifyImplementation
{
public FieldRestrictions()
{
MinCharacterLength = 0;
MaxCharacterLength = 0;
}
private int minCharacterLength;
public int MinCharacterLength
{
get { return minCharacterLength; }
set { minCharacterLength = value; RaisePropertyChanged("MinCharacterLength"); }
}
private int maxCharacterLength;
public int MaxCharacterLength
{
get { return maxCharacterLength; }
set { maxCharacterLength = value; RaisePropertyChanged("MaxCharacterLength"); }
}
}
}
public class INotifyImplementation : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public RelayCommand(Action<object> execute, object productEditCanUse) : this(execute, null)
{
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
MainViewModel.cs
public class MainViewModel : INotifyImplementation
{
public MainViewModel()
{
NewCustomer = new Customer();
NewCustomerFieldErrors = new CustomerFieldErrors();
NewCustomerFieldRestrictions = new CustomerFieldRestrictions()
{
FirstName = new FieldRestrictions()
{
MinCharacterLength = 1,
MaxCharacterLength = 5
},
LastName = new FieldRestrictions()
{
MinCharacterLength = 0,
MaxCharacterLength = 5
}
};
CreateNewCustomerCommand = new RelayCommand(CreateNewCustomer, CreateNewCustomerCanUse);
ShowNewCustomerAllFieldErrorsCommand = new RelayCommand(ShowNewCustomerAllFieldErrors, ShowNewCustomerAllFieldErrorsCanUse);
}
private Customer newCustomer;
public Customer NewCustomer
{
get { return newCustomer; }
set { newCustomer = value; RaisePropertyChanged("NewCustomer"); }
}
private CustomerFieldErrors newCustomerFieldErrors;
public CustomerFieldErrors NewCustomerFieldErrors
{
get { return newCustomerFieldErrors; }
set { newCustomerFieldErrors = value; RaisePropertyChanged("NewCustomerFieldErrors"); }
}
private CustomerFieldRestrictions newCustomerFieldRestrictions;
public CustomerFieldRestrictions NewCustomerFieldRestrictions
{
get { return newCustomerFieldRestrictions; }
set { newCustomerFieldRestrictions = value; RaisePropertyChanged("NewCustomerFieldRestrictions"); }
}
public RelayCommand CreateNewCustomerCommand { get; private set; }
protected void CreateNewCustomer(object message)
{
}
protected bool CreateNewCustomerCanUse(object message)
{
NewCustomerFieldErrors = new CustomerFieldErrors();
if (NewCustomer.FirstName.Length < NewCustomerFieldRestrictions.FirstName.MinCharacterLength)
NewCustomerFieldErrors.FirstName.Add("First Name minimum length is: " + NewCustomerFieldRestrictions.FirstName.MinCharacterLength);
if (NewCustomer.FirstName.Length > NewCustomerFieldRestrictions.FirstName.MaxCharacterLength)
NewCustomerFieldErrors.FirstName.Add("First Name maximum length is: " + NewCustomerFieldRestrictions.FirstName.MaxCharacterLength);
if (NewCustomer.LastName.Length < NewCustomerFieldRestrictions.LastName.MinCharacterLength)
NewCustomerFieldErrors.LastName.Add("Last Name minimum length is: " + NewCustomerFieldRestrictions.LastName.MinCharacterLength);
if (NewCustomer.LastName.Length > NewCustomerFieldRestrictions.LastName.MaxCharacterLength)
NewCustomerFieldErrors.LastName.Add("Last Name maximum length is: " + NewCustomerFieldRestrictions.LastName.MaxCharacterLength);
if (NewCustomerFieldErrors.FirstName.Count == 0 && NewCustomerFieldErrors.LastName.Count == 0)
return true;
return false;
}
public RelayCommand ShowNewCustomerAllFieldErrorsCommand { get; private set; }
protected void ShowNewCustomerAllFieldErrors(object message)
{
string allErrors = "";
foreach(string i in NewCustomerFieldErrors.All)
{
allErrors += i + Environment.NewLine;
}
MessageBox.Show(allErrors);
}
protected bool ShowNewCustomerAllFieldErrorsCanUse(object message)
{
return true;
}
}
MainView.xaml.cs
public partial class MainView : UserControl
{
public MainView()
{
DataContext = new MainViewModel();
InitializeComponent();
}
}
XAML
<Grid>
<StackPanel HorizontalAlignment="Left" Height="512" Margin="60,38,0,0" VerticalAlignment="Top" Width="214">
<Label Content="First Name Error:" Margin="0,20,0,0"/>
<ListBox ItemsSource="{Binding NewCustomerFieldErrors.FirstName}" Height="100"/>
<Label Content="Last Name Error:" Margin="0,20,0,0"/>
<ListBox ItemsSource="{Binding NewCustomerFieldErrors.LastName}" Height="100"/>
<Label Content="All Errors:" Margin="0,20,0,0"/>
<ListBox ItemsSource="{Binding NewCustomerFieldErrors.All}" Height="100"/>
<Button Content="Show All Errors" Margin="0,20,0,0" Command="{Binding ShowNewCustomerAllFieldErrorsCommand}" Height="40"/>
</StackPanel>
<StackPanel HorizontalAlignment="Left" Height="416" Margin="398,74,0,0" VerticalAlignment="Top" Width="214">
<Label Content="First Name" Margin="0,20,0,0"/>
<TextBox Text="{Binding NewCustomer.FirstName, UpdateSourceTrigger=PropertyChanged}" Height="100"/>
<Label Content="Last Name" Margin="0,20,0,0"/>
<TextBox Text="{Binding NewCustomer.LastName, UpdateSourceTrigger=PropertyChanged}" Height="100"/>
<Button Content="Create Customer" Margin="0,20,0,0" Command="{Binding CreateNewCustomerCommand}" Height="40"/>
</StackPanel>
</Grid>
What I expected to happen:
I expected the ListBox(C, the one bound to the All property) to list all the errors like what the MessageBox is showing.
Here's a clip of what I'm experiencing
https://gfycat.com/obesecheapkoi
I've did some new tests on Snoop
ListBox A (bound to NewCustomerFieldErrors.FirstName)
ListBox B (bound to NewCustomerFieldErrors.MiddleName)
ListBox C (bound to NewCustomerFieldErrors.All)
Apparently the ListBox C is pointing towards a blank collection, so I went to my DataContext to double check but found it to be populated, which contradicts what the ListBox C's ItemsSource is saying.
I believe your issue has to do with binding to the All property. When the binding to All is done, the Method GetAllErrors returns to it a new instance of ObservableCollection. When new errors are added, they are not added to the original instance; thus, it never needs to get refreshed.
public ObservableCollection<string> All
{
get { return GetAllErrors(); }
}
public ObservableCollection<string> GetAllErrors()
{
ObservableCollection<string> allErrors = new ObservableCollection<string>();
foreach(string i in FirstName)
{
allErrors.Add(i);
}
foreach (string i in LastName)
{
allErrors.Add(i);
}
return allErrors;
}
A BIG BIG thanks to Peter Fleischer from MSDN!
The Solution
RaisePropertyChanged(string.Empty);
Simply adding that code after I was done adding/removing contents from both the FirstName error and LastName error collections did the trick.
The Explanation
Basically my problem all along was:
The All property wasn't notified of the change
While I personally haven't confirmed this with him, my interpretation of the problem was that I was not raising the All property change, I thought that by Raising it when FirstName error and LastName error changes (through add/remove) was enough but it was not, simply adding/removing instances from the collection wasn't enough for it to warrant the Raise Property Change I placed on the FirstName error and LastName error model. So his solution was for me to manually raise it when I add/remove stuff from the collection.
I have two classes that have identical Name and Position properties. A ComboBox in a DataGrid has a list of StaffMember class taken from a database. It displays the name only but upon selection both Name and Position properties should change in the DataGrid bound to ObservableCollection of another class - Person.
So far I'm using the SelectionChanged event of the combobox to browse the VisualTree, access parent DataContext and change two properties at a time.
Is there a different approach to it?
Update. Here's an illustrating picture:
I get the Name and Position from a third party service and display the name in the combobox. As user selects a name the UI should update both Name and Position properties in the table. The table also has Age and many other columns/properties in real world. That is why there are two classes: a name/position list from a database to select from and a class which is the ItemSource of the table. I also have to deal with cases when people have the same name but different positions. Hope this explains the question better.
public class StaffMember : NotifyObject
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged("Name"); }
}
private string _position;
public string Position
{
get { return _position; }
set { _position = value; OnPropertyChanged("Position"); }
}
}
public class Person : NotifyObject
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged("Name"); }
}
private string _position;
public string Position
{
get { return _position; }
set { _position = value; OnPropertyChanged("Position"); }
}
public double Age { get; set; }
}
ViewModel:
public class ViewModel : NotifyObject
{
public ObservableCollection<Person> SelectedPeople { get; set; }
public List<StaffMember> Staff { get; set; }
public ViewModel()
{
Staff = new List<StaffMember>
{
new StaffMember { Name = "Sigmund Freud", Position = "Psychologist"},
new StaffMember { Name = "Louis Armstrong", Position = "Musician"},
new StaffMember { Name = "John Doe", Position = "Superviser"},
new StaffMember { Name = "John Doe", Position = "Manager"},
};
SelectedPeople = new ObservableCollection<Person> {
new Person { Name = "Sigmund Freud", Position = "123", Age= 161 },
new Person(),
new Person() };
}
}
public abstract class NotifyObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
public void RaiseProperychanged(string propertyName)
{
OnPropertyChanged(propertyName);
}
}
XAML:
<Grid>
<DataGrid ItemsSource="{Binding SelectedPeople}"
AutoGenerateColumns="False"
CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="ComboBoxSelect" ItemsSource="{Binding ElementName=TheMainWindow, Path=DataContext.Staff}"
SelectedValue="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}, Path=DataContext.Name, Mode=TwoWay}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectionChanged="ComboBoxSelect_SelectionChanged"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Position" Binding="{Binding Position, Mode=TwoWay}"/>
<DataGridTextColumn Header="Age" Binding="{Binding Age}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
Code-Behind:
private void ComboBoxSelect_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var comboBox = sender as ComboBox;
var parent = sender as DependencyObject;
while (!(parent is DataGridCell))
{
parent = VisualTreeHelper.GetParent(parent);
if (parent is null) return;
}
var cell = parent as DataGridCell;
if (cell == null) return;
var person = cell.DataContext as Person;
if (person == null) return;
person.Position = ((StaffMember)comboBox.SelectedItem).Position.ToString();
}
It is not a good idea to mix MVVM and code-behind.
You have a duplication of data in Person and StaffMember class.
What about idea of having StaffMember property in Person class?
public class StaffMember : NotifyObject
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged("Name"); }
}
private string _position;
public string Position
{
get { return _position; }
set { _position = value; OnPropertyChanged("Position"); }
}
}
public class Person : NotifyObject
{
private string _staffMember;
public string StaffMember
{
get { return _staffMember; }
set { _staffMember = value; OnPropertyChanged("StaffMember"); }
}
public double Age { get; set; }
}
Just wondering as to why my ObservableCollection is not binding to my Combo Box
I don't get any errors it just doesn't populate it.
public class TableList : ObservableCollection<TableName>
{
public TableList() : base()
{
Add(new TableName(1, "Notes"));
Add(new TableName(2, "TemplateNotes"));
}
}
public class TableName
{
private int noteID;
private string noteName;
public TableName(int ID, string name)
{
this.noteID = ID;
this.noteName = name;
}
public int NoteID
{
get { return noteID; }
set { noteID = value; }
}
public string NoteName
{
get { return noteName; }
set { noteName = value; }
}
}
This is my XAML
<ComboBox
x:Name="noteSaveToSelection"
HorizontalAlignment="Left"
Height="35"
Margin="155,932,0,0"
VerticalAlignment="Top"
Width="180"
ItemsSource="{Binding TableList}"
DisplayMemberPath="NoteName"
SelectedValuePath="NoteID"/>
I am new to this so i apologise if i have missed something small.
Apparently you never create an instance of your TableList class that you can actually bind to.
Create a view model class with a TableList property, e.g. like
public class ViewModel
{
public TableList TableList { get; } = new TableList();
}
Then set the DataContext property of your MainWindow to an instance of the view model class:
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
I have a vm like this
class Vm : Notifiable
{
public string Name
{
get { return _Name; }
set { _Name = value; OnPropertyChanged("Name"); }
}
private _Name = "";
}
And another like this
class CollectionVm : Notifiable
{
public ObservableCollection<Vm> Vms {get;set;}
public Vm Selected
{
get { return _Selected; }
set { _Selected= value; OnPropertyChanged("Selected"); }
}
Vm _Selected = null;
}
And a third like this
class OuterVm : Notifiable
{
CollectionVm _collection;
public Vm Display
{
get {return _collection.Selected; }
}
}
And a binding like this
<TextBlock Text={Binding Display.Name}/>
My problem is that the textblock doesn't update when the selection changes in the collection. How can I get it to do so?
This would require a mechanism by which you raise the PropertyChanged event in OuterVm.
One simple option would be to just subscribe to the events and pass them through:
class OuterVm : Notifiable
{
public OuterVm()
{
// initialize _collection
_collection.PropertyChanged += (o,e) =>
{
if (e.PropertyName == "Selected")
OnPropertyChanged("Display");
};
}
CollectionVm _collection;
public Vm Display
{
get {return _collection.Selected; }
}
}
In WPF, I have a static "Customer" object in the definition for MainWindow.xaml.cs. This customer has a publicly accessible string Name property. In expression blend 4, I click on the "Advanced Options" box beside the "Text" property for the TextBox that I would like to bind to the customer name. I then click "Data Binding..." -> "Element Property" -> "window" under "scene elements" -> click the expander arrow beside "ActiveCustomer" -> then click "Name" -> "OK". The binding is to a readonly TextBox, so One Way binding is acceptable as the default. But when I run my app, it doesn't display the customer's name. Any Suggestions?
<TextBox x:Name="AIAHNameTextBox" Height="26" Canvas.Left="90" TextWrapping="Wrap" Canvas.Top="8" Width="100" IsReadOnly="True" VerticalContentAlignment="Center" Text="{Binding ActiveCustomer.Name, ElementName=window, Mode=OneWay}" />
ActiveCustomer is an instance of my Customer class:
namespace WPFBankingSystem
{
public enum CustomerStatus
{ Open, Closed }
public enum TransferType
{ CheckingToSaving, SavingToChecking }
[Serializable]
public class Customer
{
private string address;
private Checking chkAcc;
private string name;
private int pin;
private Saving savAcc;
private string ssn;
private AccountStatus status;
private string tel;
public string Address
{
get { return address; }
set { address = value; }
}
public Checking ChkAcc
{
get { return chkAcc; }
set { chkAcc = value; }
}
public string Name
{ get { return name; } }
public int Pin
{
get { return pin; }
set { pin = value; }
}
public Saving SavAcc
{
get { return savAcc; }
set { savAcc = value; }
}
public string Ssn
{ get { return ssn; } }
public AccountStatus Status
{
get { return status; }
set { status = value; }
}
public string Tel
{
get { return tel; }
set { tel = value; }
}
public void create(string Name, string Address, string TelephoneNumber, string SSN, int PIN)
{
this.address = Address;
this.name = Name;
this.pin = PIN;
this.ssn = SSN;
this.status = AccountStatus.Open;
this.tel = TelephoneNumber;
}
public void delete()
{
if (this.chkAcc != null)
{ chkAcc.close(); }
if (this.savAcc != null)
{ savAcc.close(); }
}
public bool hasChkAcc()
{ return (this.chkAcc != null) ? true : false; }
public bool hasSavAcc()
{ return (this.savAcc != null) ? true : false; }
public void show()
{ }
public void transfer(double Amount, TransferType Type)
{
if(this.hasChkAcc() && this.hasSavAcc())
{
switch(Type)
{
case TransferType.CheckingToSaving:
this.chkAcc.Balance -= Amount;
this.savAcc.Balance += Amount;
break;
case TransferType.SavingToChecking:
this.savAcc.Balance -= Amount;
this.chkAcc.Balance += Amount;
break;
}
}
else
{ throw new Exception("You do not have both a checking account and a saving account."); }
}
public Customer()
{ }
~Customer()
{ this.delete(); }
}
}
Inside MainWindow.xaml.cs, the customer is defined just as a public Customer object:
public Customer ActiveCustomer
{ get; set; }
You cannot bind to static properties like you can to instance properties. The property ActiveCustomer then does not exist on the element named window it exists in the class MainWindow. You should be able to fix the binding by using a Source in conjunction with x:Static:
{Binding Name, Source={x:Static local:MainWindow.ActiveCustomer}}
Note that x:Static has a very specific syntax, it does not allow an arbitrary path or the like.
Even if the binding works this is problematic though as you cannot implement INPC for static properties, so if you assign a new object to ActiveCustomer there will be no update.