WPF ObservableCollection not updating view - c#

this is xaml part
<ItemsControl x:Name="EventsTop">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,1,0,0">
<Button Content="{Binding Name}" Template="{DynamicResource ButtonFirst}" Height="50" Margin="15,0,0,0" Padding="10,0,15,0" FontSize="19" FontFamily="/Resources/Fonts/Font Awesome/#FontAwesome" BorderThickness="5,0,0,0" BorderBrush="#8CC152" Background="#2980B9" HorizontalContentAlignment="Left" Foreground="Black" Click="TabOpen" Tag="{Binding Id}"></Button>
<StackPanel Background="#2980B9" Margin="15,0,0,5" Visibility="Collapsed" AllowDrop="True" Tag="{Binding Id}" Drop="RowDrop">
<Border BorderThickness="5,0,0,0" BorderBrush="#8CC152">
<StackPanel>
<DockPanel LastChildFill="False">
<Label DockPanel.Dock="Left" Width="140" Content="Date" FontSize="19" BorderThickness="0,0,0,1" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
<Label DockPanel.Dock="Left" Width="190" Content="Event" FontSize="19" BorderThickness="0,0,0,1" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
<Label DockPanel.Dock="Left" Width="100" Content="Select" FontSize="19" BorderThickness="0,0,0,1" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
</DockPanel>
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="150">
<ItemsControl ItemsSource="{Binding Details}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DockPanel LastChildFill="False">
<Label Content="{Binding Date}" DockPanel.Dock="Left" Width="140" FontSize="19" BorderThickness="0" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
<Label Content="{Binding EventName}" DockPanel.Dock="Left" Width="165" FontSize="19" BorderThickness="0" FontFamily="/Resources/Fonts/Open Sans/#Open Sans" BorderBrush="Black" HorizontalContentAlignment="Center"></Label>
<Border Width="97">
<CheckBox VerticalAlignment="Center" HorizontalAlignment="Center" IsChecked="{Binding Checked}"></CheckBox>
</Border>
<Button Width="25" DockPanel.Dock="Left" Content="" BorderThickness="0" Background="Transparent" FontFamily="/Resources/Fonts/Font Awesome/#FontAwesome"></Button>
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</StackPanel>
</Border>
</StackPanel>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
this is xaml.cs
private void WindowLoaded(object sender, RoutedEventArgs e)
{
EventHelper eventHelper = new EventHelper();
TopEvents = eventHelper.GetSports(EventHelper.EventGroup.Top);
foreach (Sport item in TopEvents)
{
item.Name = "\uf196 " + item.Name;
}
EventsTop.ItemsSource = TopEvents;
AllEvents = eventHelper.GetSports(EventHelper.EventGroup.All);
foreach (Sport item in AllEvents)
{
item.Name = "\uf196 " + item.Name;
}
EventsAll.ItemsSource = AllEvents;
Sport.ItemsSource = eventHelper.GetSports(EventHelper.EventGroup.All);
}
private void RowMouseDown(object sender, MouseButtonEventArgs e)
{
DockPanel currentRow = (DockPanel) sender;
int rowOffset = Convert.ToInt32(currentRow.Tag);
DragDrop.DoDragDrop(currentRow,rowOffset,DragDropEffects.Copy);
}
private void RowDrop(object sender, DragEventArgs e)
{
int rowOffset = (int) e.Data.GetData(typeof (int));
AllEvents[0].Name = "1";
}
Also my model in collection
class Sport : INotifyPropertyChanged
{
private int _id;
private string _name = string.Empty;
private ObservableCollection<Details> _details = new ObservableCollection<Details>();
public int Id
{
get { return _id; }
set { _id = value; }
}
public string Name
{
get { return _name; }
set
{
_name = value;
NotifyPropertyChanged("Content");
}
}
public ObservableCollection<Details> Details
{
get { return _details; }
set { _details = value; }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
MessageBox.Show(info);
}
}
}
So when I am changing property its throwing MessageBox but not updating GUI.
I xaml.cs I am calling methods GetEvents thats
return ObservableCollection
I want to change Name in Sport which is in ObservableCollaction<Sport> AllEvents
You can see it in RowDrop method in xaml.cs
In debugging I notice that AllEvents[0].Name was changed but view was not updating
UPDATE
Part of ObservabelCollection declaration
public MainPage()
{
InitializeComponent();
AllEvents = new ObservableCollection<Sport>();
TopEvents = new ObservableCollection<Sport>();
EventsTop.ItemsSource = TopEvents;
EventsAll.ItemsSource = AllEvents;
}
private ObservableCollection<Sport> AllEvents;
private ObservableCollection<Sport> TopEvents;
UPDATE SECOND
I caught that when I am using window activated event it is working

I found solution.
So, ObservableCollection is working very well but,It needs to be refreshed
for appearing in view and for it we need to use
CollectionViewSource.GetDefaultView(ObservableCollection).Refresh()
method for it
I think it will help someone

The problem with property named passed to NotifyPropertyChanged method. The name of parameter should be property name. Please change the Name property as
public string Name
{
get { return _name; }
set
{
_name = value;
NotifyPropertyChanged("Name");
}
}

Use CallerMemberNameAttribute to avoid having to get the name correct and allowing refactoring:
private void NotifyPropertyChanged([CallerMemberName] string info = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
MessageBox.Show(info);
}
}
public string Name
{
get { return _name; }
set
{
_name = value;
NotifyPropertyChanged(); //now no need to specify
}
}
Every property setter should notify property change, so:
public IEnumerable<Details> Details //note IEnumerable, no calling code needs to know its concrete type
{
get { return _details; }
set
{
_details = value;
NotifyPropertyChanged();
}
}
And with an observable range collection you could do this:
private readonly ObservableRangeCollection<Details> _details = new ObservableRangeCollection<Details>();
public IEnumerable<Details> Details
{
get { return _details; }
set { _details.Replace(value); }
}

From MSDN.
Occurs when an item is added, removed, changed, moved, or the entire
list is refreshed.
The changed does not mean when child properties are changed, but when you change the item at any index.
So when you modify a collection item you will need to notify the binding that the property was changed. From your window's viewmodel after you have modified the item in the collection, you would notify that the collection was changed.
NotifyPropertyChanged("AllEvents");

Related

combobox binding MVVM C#

Im missing something but i have no idea what :(
I've bind IEnumerable collection to combobox. I would like to use its selected value as parameter for shutdown command, however when i press start button it doesn't load selected values.
I've followed few tutorials to understand MVVM but there is still something missing but i cant figured out what.
Here is MainWindow.xaml :
<grid>
<StackPanel>
<!--Title label-->
<TextBlock Text="Wyłącz komputer za:" Margin="5"/>
<!-- Blocks used to set hours and minutes-->
<StackPanel Orientation="Horizontal">
<TextBlock Text="Godziny:" Margin="5"/>
<ComboBox x:Name="HoursCB" Margin="5" Width="40" ItemsSource="{Binding myHours}" SelectedValue="{Binding selectedHours, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="Minuty:" Margin="5" />
<ComboBox x:Name="MinutesCB" Margin="5" Width="40" ItemsSource="{Binding myMinutes}" SelectedValue="{Binding selectedMinutes, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel >
<!-- Timer -->
<StackPanel Orientation="Horizontal">
<Label x:Name="HHLabel" Content="{Binding selectedHours}" FontSize="30" HorizontalAlignment="Center" Width="45"/>
<Label x:Name="Colon1" Content=":" FontSize="30" HorizontalAlignment="Center" Width="25"/>
<Label x:Name="MMLabel" Content="{Binding selectedMinutes}" FontSize="30" HorizontalAlignment="Center" Width="45"/>
<Label x:Name="Colon2" Content=":" FontSize="30" HorizontalAlignment="Center" Width="25"/>
<Label x:Name="SSLabel" Content="00" FontSize="30" HorizontalAlignment="Right" Width="45"/>
</StackPanel>
<!-- Start Button -->
<Button Content="uruchom odliczanie" Margin="5" Command="{Binding StartCommand}" />
<!-- Stop Button-->
<Button Content="Zatrzymaj odliczanie" Margin="5" Command="{Binding StopCommand}"/>
</StackPanel>
</grid>
and here is view model :
class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
StartCommand = new AddNameCommand(this);
}
class AddNameCommand : ICommand
{
MainWindowViewModel parent;
public AddNameCommand(MainWindowViewModel parent)
{
this.parent = parent;
parent.PropertyChanged += delegate { CanExecuteChanged?.Invoke(this, EventArgs.Empty); };
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{ return true; }
public void Execute(object parameter)
{
int num = parent.SelectedHours * 3600 + parent.SelectedMinutes * 60;
MessageBox.Show($"Shutting down the computer in {num} !");
//Process.Start("shutdown", string.Format("/s /t {0}", num));
}
}
public ICommand StartCommand { get; private set; }
/// <summary>
/// Combobox Items.
/// </summary>
//public IEnumerable<int> myHours = Enumerable.Range(0, 23);
//public IEnumerable<int> myMinutes = Enumerable.Range(1, 59);
public ObservableCollection<int> myHours { get; set; } = new ObservableCollection<int>(Enumerable.Range(0, 23));
public ObservableCollection<int> myMinutes { get; set; } = new ObservableCollection<int>(Enumerable.Range(1, 59));
/// <summary>
/// Selected time properties.
/// </summary>
public int SelectedMinutes
{
get { return mSelectedMinutes; }
set
{
if (value == mSelectedMinutes)
return;
mSelectedMinutes = value;
OnPropertyChanged();
}
}
int mSelectedMinutes;
public int SelectedHours
{
get { return mSelectedHours; }
set
{
if (value == mSelectedHours)
return;
mSelectedHours = value;
OnPropertyChanged();
}
}
int mSelectedHours;
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName]string propertyName = null)
{ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
}
You should change your xaml to the following (note the case sensitive SelectedHours/Minutes):
<!-- Blocks used to set hours and minutes-->
<StackPanel Orientation="Horizontal">
<TextBlock Text="Godziny:" Margin="5"/>
<ComboBox x:Name="HoursCB" Margin="5" Width="40" ItemsSource="{Binding myHours}" SelectedValue="{Binding SelectedHours, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="Minuty:" Margin="5" />
<ComboBox x:Name="MinutesCB" Margin="5" Width="40" ItemsSource="{Binding myMinutes}" SelectedValue="{Binding SelectedMinutes, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel >
Binding errors can be easily detected by opening the Output Window in Visual Studio and looking for the following:
System.Windows.Data Error: 40 : BindingExpression path error: 'selectedHours' property not found on 'object' ''MainWindowViewModel' (HashCode=46431654)'. BindingExpression:Path=selectedHours; DataItem='MainWindowViewModel' (HashCode=46431654); target element is 'ComboBox' (Name='HoursCB'); target property is 'SelectedValue' (type 'Object')
You have not binded the Selected Values of combo boxes to the right property in the View Model. Just change "selectedHours" to "SelectedHours" and "selectedMinutes" to "SelectedMinutes" in your XAML to bind it properly.
You code is behaving like i expedted it. Your problem is the Enumerable.Range function. It starts with an inclusive 0 and then counts up 23 times Inclunding 0

WPF How do I evaluate a property to make binding

I'm doing a custom control for our company, and I want to define DataTemplate of elements into a ResourceDictionary, for more genericity and skin handling.
My control has a ItemsSource property that contains all collection. I also have a DependencyProperty into my control that specificy the name of the property of current Item to bind on.
Some code :
<DataTemplate x:Key="VEGA_TokenTemplate">
<Border x:Name="Bd" BorderBrush="{StaticResource VEGA_TokenBorderBrush}" BorderThickness="1" Background="{StaticResource VEGA_TokenBackgroundBrush}" Padding="1" Margin="1,5" HorizontalAlignment="Stretch" SnapsToDevicePixels="True">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding WHAT_HERE}" HorizontalAlignment="Stretch" VerticalAlignment="Center" />
<Button Background="Transparent" Content="X" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="10" FontFamily="Berlin Sans FB" Grid.Column="1" Command="{Binding RelativeSource={RelativeSource AncestorType=local:TokenTextBox}, Path=TokenDeleteButtonCommand}"
CommandParameter="{Binding WHAT_HERE}" IsEnabled="True" />
</Grid>
</Border>
</DataTemplate>
In this DataTemplate, I would like to replace the WHAT_HERE tag by the evaluation of my dependency property.
For example, if I set "Email" on my dependency property, I would like the Binding to be like "Path=Email". However, I only have "Email" as litteral into my component. How can I do such a Binding ?
I hope I'm clear in my explainations...
Thank you
I would use Behaviors in this situation or attached properties. I am sure there are other variation of how you can accomplish this. But here is one way to give you an idea
//test interface and test class
public interface IProvidePropertyToBindTo
{
string GetPropertyToBindTo();
}
public class TestChoosingPropertyToBind : IProvidePropertyToBindTo, INotifyPropertyChanged
{
#region Fields
public event PropertyChangedEventHandler PropertyChanged;
private string _emailAddress;
private string _name;
private string _propertyName;
#endregion Fields
#region Properties
public string EmailAddress
{
get { return _emailAddress; }
set
{
if (_emailAddress == value)
return;
_emailAddress = value;
OnPropertyChanged();
}
}
public string Name
{
get { return _name; }
set
{
if (_name == value)
return;
_name = value;
OnPropertyChanged();
}
}
public string PropertyToBindTo
{
set { SetPropertToBindTo(value); }
}
#endregion
#region Methods
public string GetPropertyToBindTo()
{
return _propertyName;
}
public void SetPropertToBindTo(string propertyName)
{
var prop = GetType().GetProperty(propertyName);
if (prop == null)
throw new Exception("Property : "+propertyName+" does not exist in this object {"+this.ToString()+"}.");
_propertyName = propertyName;
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion Methods
}
Test Data
public ObservableCollection<TestChoosingPropertyToBind> Test
{
get
{
return new ObservableCollection<TestChoosingPropertyToBind>(
new List<TestChoosingPropertyToBind>()
{
new TestChoosingPropertyToBind(){EmailAddress = "Test#test.com", PropertyToBindTo = "EmailAddress"},
new TestChoosingPropertyToBind(){Name = "Test", PropertyToBindTo = "Name"}
}
);
}
}
An edited snippet of your data template with the custom behavior
<DataTemplate x:Key="VEGA_TokenTemplate">
<Border x:Name="Bd" BorderBrush="Red" BorderThickness="1" Background="White" Padding="1" Margin="1,5" HorizontalAlignment="Stretch" SnapsToDevicePixels="True">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding WHAT_HERE}" HorizontalAlignment="Stretch" VerticalAlignment="Center" >
<i:Interaction.Behaviors>
<BehaviorLocationNamespace:MyCustomBehavior></BehaviorLocationNamespace:MyCustomBehavior>
</i:Interaction.Behaviors>
</TextBlock>
<Button Background="Transparent"
Content="X"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="10" FontFamily="Berlin Sans FB" Grid.Column="1" IsEnabled="True" />
</Grid>
</Border>
</DataTemplate>
//Items Control usage
<ItemsControl ItemTemplate="{StaticResource VEGA_TokenTemplate}" ItemsSource="{Binding Test}">

How to create listbox from list

How can I add items to listbox when item source is a list.
XAML:
<ListBox Grid.Row="2" HorizontalAlignment="Stretch" ItemsSource="{Binding Source={StaticResource viewModel}, Path=CultureEvents}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Source={StaticResource viewModel}, Path=ItemTitle}" Height="30" HorizontalAlignment="Left" Margin="116,364,0,0" VerticalAlignment="Top" Width="334" Foreground="White" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In viewmodel I have list:
public List<CultureEvent> CultureEvents { get; set; }
And property:
public string ItemTitle
{
get
{
return ?;
}
set
{
? = value;
OnPropertyChanged(new PropertyChangedEventArgs("ItemTitle"));
}
}
But I don't know what to put into property.
private string _itemTitle
public string ItemTitle
{
get
{
return _itemTitle;
}
set
{
_itemTitle = value;
OnPropertyChanged(new PropertyChangedEventArgs("ItemTitle"));
}
You would generate The list something like this,
CultureEvents = new List<CultureEvent>();
CultureEvents.Add(new CultureEvent{Title = "Yourvalue"} );

Binding not working?

Most of my bindings are working fine but one just displays: Test.Models.PersonModel
The property ("Name") where I like to bind to is in this class.
Here the part where I bind:
<ItemsControl ItemsSource="{Binding Persons}">
<StackPanel Margin="24, 4, 4, 4"
Orientation="Horizontal">
<TextBlock FontSize="{StaticResource PhoneFontSizeExtraLarge}"
FontFamily="{StaticResource PhoneFontFamilyLight}"
Text="{Binding Name}"
VerticalAlignment="Center"/>
</StackPanel>
</ItemsControl>
Persons is a OberservableCollection of the type PersonModel. Here the code of the PersonModel:
public class PersonModel : INotifyPropertyChanged
{
private string _name = null;
public string Name
{
get { return _name; }
set { _name = value; NotifyPropertyChanged("Name"); }
}
private BitmapImage _profilpicture = null;
public BitmapImage ProfilPicture
{
get { return _profilpicture; }
set { _profilpicture = value; NotifyPropertyChanged("ProfilPicture"); }
}
#region PropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
You should use ItemTemplate (msdn):
<ItemsControl ItemsSource="{Binding Persons}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="24, 4, 4, 4"
Orientation="Horizontal">
<TextBlock FontSize="{StaticResource PhoneFontSizeExtraLarge}"
FontFamily="{StaticResource PhoneFontFamilyLight}"
Text="{Binding Name}"
VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Failing To Bind Dynamically Generated Buttons & Textboxes in WPF

I was working on dynamic generation of labels, buttons and Textbox in my WPF application. Well I was successful in dynamically creating them but I am facing one major issue in it.
Xaml:
<ListBox x:Name="myViewChannelList" HorizontalAlignment="Stretch" Height="Auto" ItemsSource="{Binding}" Margin="0" VerticalAlignment="Stretch" Width="Auto">
<ListBox.ItemTemplate>
<DataTemplate >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="170" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{Binding Path=ChanelName}" Margin="50,20,0,0"></Label>
<Grid Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding Path=VoltageText}" Height="25" Width="50" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" />
<Button Grid.Column="1" Content="Set" Height="25" Command="{Binding ElementName=myViewChannelList, Path=DataContext.SetCommand}" Width="50" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" ></Button>
</Grid>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Model Class:
private string _ChanelName = "";
public String ChanelName
{
get
{
return _ChanelName;
}
set
{
if (value != _ChanelName)
{
_ChanelName = value;
OnPropertyChanged("ChanelName");
}
}
}
// Constructor
public VoltageModel(string ChanelName)
{
this.ChanelName = ChanelName;
}
public override string ToString()
{
return _ChanelName;
}
ViewModel Class:
class ChannelList : ObservableCollection<VoltageModel>, INotifyPropertyChanged
{
private string _VoltageText;
public string VoltageText
{
get { return _VoltageText; }
set
{
_VoltageText = value;
OnPropertyChanged("VoltageText");
}
}
// Method gets called when Set Button Is Clicked
public void SetCommandExecuted()
{
string val = VoltageText;
}
//Notify Property Changed members are present
}
Xaml.cs Class:
ChannelList myChanels = new ChannelList();
public VoltageView() // Constructor
{
InitializeComponent();
myChanels.Add(new VoltageModel("VDD__Main"));
myChanels.Add(new VoltageModel("VDD__IO__AUD"));
myChanels.Add(new VoltageModel("VDD__CODEC__AUD"));
myViewChannelList.DataContext = myChanels;
}
This gives me 3 Labels(Content as above), 3 textboxes and 3 buttons when I run the application.
Now when I enter the value inside the textbox it shows null on button click when I put a breakpoint in SetCommandExecuted(). Most importantly any of the 4 button I click generates the event. I want the first textbox and first button to be in sync(bind), 2nd textbx and 2nd button to be in sync and so on. Basically each control must be in sync with the other control in a row. It should not effect the other rows. Is it possible???
Here is the solution to your question. As general practice you want to avoid all logic, building your data, etc. in the code behind. All the business logic should be in the view model which will make it easier to unit test.
Here is the view
.xaml
<StackPanel>
<ListBox HorizontalAlignment="Stretch"
Height="Auto"
ItemsSource="{Binding VoltageCollection}"
VerticalAlignment="Stretch"
Width="Auto">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Width="100"
Content="{Binding ChannelName}" />
<TextBox Width="100"
Text="{Binding VoltageText}" />
<Button Margin="10,0,0,0"
Content="Set"
Command="{Binding VoltageCommand}"
CommandParameter="{Binding VoltageText}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
Here is the code behind
.xaml.cs
private ChannelListViewModel m_voltageViewModel;
public MainWindow()
{
InitializeComponent();
m_voltageViewModel = new ChannelListViewModel();
m_voltageViewModel.Initialize();
DataContext = m_voltageViewModel;
}
Here is the Model: VoltageModel
public class VoltageModel : INotifyPropertyChanged
{
public string ChannelName { get; set; }
private string m_voltageText;
public string VoltageText
{
get { return m_voltageText; }
set
{
m_voltageText = value;
OnPropertyChanged("VoltageText");
}
}
public ICommand VoltageCommand { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Here is the ViewModel: ChannelListViewModel
public class ChannelListViewModel
{
private ICommand m_voltageCommand;
public ChannelListViewModel()
{
m_voltageCommand = new DelegateCommand(x => SetCommandExecute(x));
}
public void Initialize()
{
VoltageCollection = new ObservableCollection<VoltageModel> { new VoltageModel() { ChannelName = "VDD__Main", VoltageText = String.Empty, VoltageCommand = m_voltageCommand },
new VoltageModel() { ChannelName = "VDD__IO__AUD", VoltageText = String.Empty, VoltageCommand = m_voltageCommand },
new VoltageModel() { ChannelName = "VDD__CODEC__AUD", VoltageText = String.Empty, VoltageCommand = m_voltageCommand }};
}
public ObservableCollection<VoltageModel> VoltageCollection { get; set; }
public void SetCommandExecute(object voltageText)
{
Debug.WriteLine(voltageText);
}
}
Finally simple DelegateCommand class DelegateCommand
public class DelegateCommand : ICommand
{
Action<object> m_executeDelegate;
public DelegateCommand(Action<object> executeDelegate)
{
m_executeDelegate = executeDelegate;
}
public void Execute(object parameter)
{
m_executeDelegate(parameter);
}
public bool CanExecute(object parameter) { return true; }
public event EventHandler CanExecuteChanged;
}
i didn't get much into what was wrong since i recognized 2 things that were generally very wrong ,and they might be the problem for unexpected behavior on your part .
the first : your DataTemplate places your control one on top of the other .
fix :
<DataTemplate >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{Binding Path=ChanelName}" />
<TextBox Grid.Column="1" Text="{Binding Path=VoltageText}" />
<Button Grid.Column="2" Command="{Binding ElementName=myViewChannelList, Path=DataContext.SetCommand}" />
</Grid>
</DataTemplate>
the second : your Properties are set after PropertyChanged event was risen so they would not be updated until the next time you input a value.
fix :
private T _property;
public T Property
{
get { return _property; }
set
{
_property = value;
OnPropertyChanged("Property");
}
}
make these fixes and edit your post if you still have issues post a comment under my answer.

Categories