Reputation: 166
I am on my first bigger WPF Program, many Windows and ViewModel, and could help myself just fine until now.
At first i had 2 List, one List<double> Factor
, one List<string> Name
, and I tried to bind both to one ListView. It didn't work, and I thought a Dictionary would be better.
So now I have a Dictionary<string, double> IngList = new Dictionary<string, double>();
After Clicking a Button the Content of 2 TextBox should get added to the Dictionary and then Displayed on my ListView.
(Just a small portion of the Code, else it would take up to much space)
My ViewModel:
namespace FoodsLib.ViewModel
{
public class ViewModelAddRecipeWindow : ViewModelBase, INotifyPropertyChanged
{
public ViewModelAddRecipeWindow( IViewControl vctrl)
{
AddIngredientCmd = new RelayCommand(() => AddToList()
_viewControl = vctrl;
}
}
protected IViewControl _viewControl;
new public event PropertyChangedEventHandler PropertyChanged;
new protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
protected string _ingredientR, _name, _stringtype, _stringCategory, _recipe;
public double Factor
{
get { return _factor; }
set
{
if (_factor != value)
{
_factor = value;
OnPropertyChanged("Factor");
}
}
}
public string IngredientR
{
get { return _ingredientR; }
set
{
if (_ingredientR != value)
{
_ingredientR = value;
this.OnPropertyChanged("IngredientR");
}
}
}
Dictionary<string, double> IngList = new Dictionary<string, double>();
public void AddToList()
{
if (!IngList.ContainsKey(IngredientR))
{
IngList.Add(IngredientR, Factor);
_viewControl.ShowMessage("Added", "Ingredient");
}
else
{
_viewControl.ShowMessage("You can't add an Ingredient twice", "Ingredient Error.");
return;
}
}
public ICommand AddIngredientCmd { get; set; }
}
}
And my View:
<Grid Grid.Row="2" Grid.Column="3" HorizontalAlignment="Left"
Margin="5,5,5,5" Grid.ColumnSpan="2" Grid.RowSpan="6">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="240"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox x:Name="tbAddFood" Grid.Row="0" Grid.Column="1" Text="{Binding IngredientR, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"
Width="160" Margin="5" HorizontalAlignment="Left"/>
<TextBox x:Name="tbAddFoodAmount" Grid.Row="1" Grid.Column="1" Text="{Binding Factor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Width="50" Margin="5" HorizontalAlignment="Left"/>
<Label Grid.Row="0" Grid.Column="0" Content="Ingredients" HorizontalAlignment="Right"
Margin="5" Foreground="#ebeff4"/>
<Label Grid.Row="1" Grid.Column="0" Content="Amount" HorizontalAlignment="Right"
Margin="5" Foreground="#ebeff4"/>
<Button x:Name="btAddIngredient" Grid.Row="1" Grid.Column="1"
Command="{Binding Path=AddIngredientCmd}" Content=" Add " Margin="5,5,30,5"
BorderBrush="#415578" BorderThickness="0"
HorizontalAlignment="Center" Background="#415578" Foreground="#ebeff4"/>
<ListView x:Name="lbFoodList" Grid.Column="1" Grid.Row="2" Margin="5" Height="120" VerticalAlignment="Top"
Foreground="#ebeff4" ItemsSource="{Binding IngList}"
ScrollViewer.VerticalScrollBarVisibility="Visible" Grid.RowSpan="4">
<ListView.View>
<GridView>
<GridView.ColumnHeaderContainerStyle>
<Style>
<Setter Property="FrameworkElement.Visibility" Value="Collapsed"/>
</Style>
</GridView.ColumnHeaderContainerStyle>
<GridViewColumn Width="Auto" DisplayMemberBinding="{Binding Key, Mode=OneWay}"></GridViewColumn>
<GridViewColumn Width="Auto" DisplayMemberBinding="{Binding Value, Mode=OneWay}"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
I get to the point where the Dictionary gets filled with both items, but the ListView won't display anything.
I am not asking for a complete Code, just a "how" and "why". TY
Edit:
Using an ObservableCollection did the trick.
public ObservableCollection<tempIng> _ListMF = new
ObservableCollection<tempIng>();
public ObservableCollection<tempIng> ListMF
{
get { return _ListMF; }
set { _ListMF = value; OnPropertyChanged("_ListMF"); }
}
with a new Class tempIng, which gets the Name and Factor after clicking "Add".
public class tempIng
{
public string Name { get; set; }
public double Factor { get; set; }
public override string ToString()
{
return this.Name + ", " + this.Factor ;
}
}
Ty, and I setted the DataContext in the .xaml.cs
Would it also work with a List ?
Upvotes: 1
Views: 5448
Reputation: 9857
You can only bind to properties. Try making your list an
public ObservableCollection<KeyValuePair> IngList { get; private set; }
I also don't see you setting the DataContext so here's an example of that also if that sounds new.
<Control>
<Control.Resources>
<ViewmodelNamespace:ViewModelAddRecipeWindow x:Key="ReceipieViewModel"/>
</Control.Resources>
<Grid DataContext="{StaticResource ReceipieViewModel}">
<ListView ItemsSource="{Binding IngList}"/>
</Grid>
</Control>
Here is a Tutorial on binding to a list in WPF
Upvotes: 1