Dictionary filled with elements, but the binding is not happening. What's the problem?
<combobox margin="0,0,10,0" itemssource="{Binding clients}" selectedvaluepath="Key" displaymemberpath="Value"></combobox>
To declare and initialize a Dictionary variable
Dictionary<string, string> clients;
public AddOrder()
{
InitializeComponent();
connection = new OleDbConnection(ConfigurationManager.ConnectionStrings["AccessBarbershop"].ConnectionString);
clients = GetClients();
}</string>
Method that returns the Dictionary.
private Dictionary<string, string> GetClients()
{
Dictionary<string, string> clients = new Dictionary<string, string>();
using (connection)
{
if (connection.State != ConnectionState.Open)
connection.Open();
string request = "SELECT Codcliente, name FROM Customers";
using (OleDbCommand command = new OleDbCommand(request, connection))
using (OleDbDataReader reader = command.ExecuteReader())
while (reader.Read())
clients.Add(reader["Codcliente"].ToString(), reader["name"].ToString());
}
return clients;
}</string></string></string>
Changed methods added class.
private ObservableCollection<clients> GetClients()
{
var clients = new ObservableCollection<clients>();
if (connection.State != ConnectionState.Open)
connection.Open();
string request = "SELECT Codcliente, name FROM Customers";
using (OleDbCommand command = new OleDbCommand(request, connection))
using (OleDbDataReader reader = command.ExecuteReader())
while (reader.Read())
clients.Add(new Clients(reader["Codcliente"].ToString(), reader["name"].ToString()));
return clients;
}
}
public class Client : INotifyPropertyChanged
{
public Client(string id, string name)
{
ID = id; Name = name;
}
string id;
public string ID
{
get { return id; }
set { id = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ID")); }
}
string name;
public string Name
{
get { return name; }
set { name = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name")); }
}
public event PropertyChangedEventHandler PropertyChanged;
}</clients></clients>
<combobox margin="0,0,10,0" itemssource="{Binding clients}" selectedvaluepath="ID" displaymemberpath="Name"></combobox>
Solution
In General, it looks adequate. What is specifically expressed in dormant binding? What do you do with clients that is not reflected in the combobox? - Breana_Leffl commented on July 8th 19 at 16:51
Binding in Debug mode and write it to the Output window binding errors, if any. Run the program and see if errors in the Output window - Breana_Leffl commented on July 8th 19 at 16:57
1) in AddOrder.xaml {Binding clients} change to {Binding Clients}
2) from AddOrder.cs can all be removed, except for the constructor. In the constructor, leaving only the call to InitializeComponents();
3) ClientsViewModel.cs type properties Clients are changing with an IEnumerable (I don't know why you decided to put as IEnumerable, exhibit collection needs so that the INotifyCollectionChanged interface was visible. And you "cut", exposing the collection as IEnumerable, binding is thought that there is not ObservableCollection, and primitive enumerable object) on the ObservableCollection. Make a public property - you don't put the access modifier public, in sharp by default, all private.
4) AddOrderButton_Click right after the line creating the window (AddOrder addOrder = new AddOrder();) write the following:
addOrder.DataContext = new ClientsViewModel();
Is setting the data context for the window, in fact it is the most important thing, because without it binding in principle, do not know to which object to bind to. All of the properties specified in the bindings (for example, Clients in your case) are searched in the current DataContext, which can be specified as a whole for the window (in most cases for simple Windows like your order is Added) and for a specific control (in particular, you can set the DataContext via the binding to the DataContext property of the parent).
Comments on the styling, which will simplify your understanding and work:
1) AddOrder and AddService suggest to rename AddOrderWindow and AddServiceWindow. First, it is still Windows, and secondly, don't suggest to name the classes of verb names (with the exception of classes of functors, but in Sharpe that possibility is still there). The class is an entity, so it is almost always a noun. Even if your class is created for a specific action, call it a verbal noun, such as the StreamReader or JsonSerializer;
2) rename the class Clients in the ClientViewModel, and now the confusion arises;
3) CallerMemberName is in principle a solution to the problem of transfer of title of the properties, but it's an old crutch with a not so obvious behavior and fit it not always. Now it is convenient and correct to use the nameof operator:
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ID)));
instead
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ID"));
The nameof operator gives you the security of renaming properties because the compiler substitutes the string literal on the transmitted identifier, you can rename the properties, including the means of refactoring and you get so that the Name property is renamed to FullName, and the arguments of the event still passes the literal "Name". And Yes, to use CallerMemberName, you need to pass a parameter to a NotifyPropertyChanged to the compiler framed it myself. - Breana_Leffl commented on July 8th 19 at 17:12
The rest happened? - Breana_Leffl commented on July 8th 19 at 17:18
System.Windows.Data Error: 40 : BindingExpression path error: 'Сlients' property not found on 'object' "AddOrderViewModel' (HashCode=31470215)'. BindingExpression:Path=Сlients; DataItem='AddOrderViewModel' (HashCode=31470215); target element is 'ComboBox' (Name="); target property is 'ItemsSource' (type 'IEnumerable')
Very strange that the object AddOrderViewModel failed to find property Clients, because it there still is. Therefore, check into the classic mistake of a Russian programmer, and see that you accidentally wrote the Russian letter With the name of the properties Clients in the AddOrder.xaml - Breana_Leffl commented on July 8th 19 at 17:30