INotifyPropertyChanged on a property that contains an i list - wpf

Hi i am using this code in myClass to change content in my wpf applciation
public event PropertyChangedEventHandler PropertyChanged;
protected void Notify(string propertyName)
{
if (this.PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Everytime i change a property in myClass it changes the labels that i have in my app.
<Label Content="{Binding Category}" Padding="7,0,0,0" />
this works just fine but in myClass i have an property contains an ilist to another class Article
private IList<Article> m_articles = new List<Article>();
Now to myquestion the Notify method doesnt update the content in my the Ilist is there i way to make it update with an ilist and view. All property in myclass works fine if it is an string or int but when it is a Ilist it wont update. Hope you guys understand what i mean my english is bad sry..
Thanks for help
here the code in xaml
<ListBox Name="ArtInfo" ItemsSource="{Binding Path=Articles}">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Artnr}" />
</DataTemplate>
</ListBox.ItemTemplate>
{Binding Path=Articles} <-- this is the property that contains an ilist
<-- this is an property in the Article class

You should use an ObservableCollection<Article> instead of a List<Article>

Related

Textblock in a listview doesn't show the bind data - WPF XAML

I'm trying to bind the data with text block in a listview but it doesn't show the data. However, when I run the application, I can see the list is created but it display the empty data. See the empty list of data in the below image:
Here's my XAML code:
<ListView Margin="20,0,0,20" x:Name="listView_attachedFiles">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Width="100" Text="{Binding AttachedFiles, Mode=TwoWay, NotifyOnTargetUpdated=True}">
<Hyperlink>
</Hyperlink>
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Here's the C# Code
public class ListviewModel : INotifyPropertyChanged
{
private ObservableCollection<string> _attachedfiles;
public ObservableCollection<string> AttachedFiles
{
get { return _attachedfiles; }
set
{
_attachedfiles = value;
OnPropertyChanged("AttachedFiles");
}
}
public ListviewModel()
{
AttachedFiles = new ObservableCollection<string>();
}
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName">The property that has a new value.</param>
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Here's is how I'm populating the data:
// I'm calling this method to attach the list of filenames
private void ExecuteMethod_AttachFile(object Parameter)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = true;
if (ofd.ShowDialog() == true)
{
AttachedFileLocation = ofd.FileNames.ToList();
// adding bind data to the list of viewmodel: adding attachefile names
foreach (var file in AttachedFileLocation)
{
FileInfo info = new FileInfo(file);
DMS_Form.Instance.ListofViewModel.AttachedFiles.Add(info.Name + " X");
}
}
}
Here's is how I'm attaching the itemssource reference in the constructor of the WPF Form.
//Binding the list of attached files with the listview
listView_attachedFiles.ItemsSource = ListofViewModel.AttachedFiles;
Please help me figure out where I'm making the mistake. Any help would be highly appreciated. Thank you
Ali
With some hours of research, I realized there was a bit problem with my code. The solution is to first define data context in the WPF Form constructor method i.e
listView_attachedFiles.DataContext = ListofViewModel;
second update this XAML code
<TextBlock Width="100" Text="{Binding AttachedFiles, Mode=TwoWay, NotifyOnTargetUpdated=True}">
with this XAML code.
<TextBlock Width="100" Text="{Binding}">
Now save, and build the application, run it.

WPF Custom Control Dependency Property setter not getting called?

I have created a custom control CustomTextBox inherited from TextBox class. I have created a dependency property named CustomTextProperty.
I have binded this DP with my Viewmodel property.
While Registering the DP i have given the property change callback but it is only get called one time when my control gets the binded data initially when my xaml loads.
When i try to set my control from view the binded VM property setter does not gets called and also the propertychangecallback not gets fired.
Please help!!
Code snipet below:
My Custom control
class CustomTextBox : TextBox
{
public static readonly DependencyProperty CustomTextProperty = DependencyProperty.Register("CustomText",
typeof(string), typeof(CustomTextBox),
new FrameworkPropertyMetadata("CustomTextBox",
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(OnCustomPropertyChange)));
public string CustomText
{
get { return (string)GetValue(CustomTextProperty); }
set { SetValue(CustomTextProperty, value); }
}
private static void OnCustomPropertyChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// This is Demo Application.
// Code to be done Later...
}
}
My View Model:
public class ViewModel : INotifyPropertyChanged
{
private string textForTextBox;
public string TextForCustomTextBox
{
get
{
return this.textForTextBox;
}
set
{
this.textForTextBox = value;
this.OnPropertyChange("TextForCustomTextBox");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChange(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
My Xaml Code with Binding:
<custom:CustomTextBox x:Name="CustomTextBox"
CustomText="{Binding TextForCustomTextBox, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Row="1" HorizontalAlignment="Center" Width="200" Height="50" />
My Code Behind to set DataContext:
// My View Constructor
public View1()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
You said that you declared a CustomText DependencyProperty and data bound it to your view model TextForCustomTextBox property and that much is correct. However, when you said that you tried to set your property from the view, you were mistaken.
What you were actually doing was setting the CustomTextBox .Text property from the view and that wasn't connected to your CustomTextBox.CustomText property. You can connect them like this, although I'm not quite sure what the point of that would be:
<Views:CustomTextBox x:Name="CustomTextBox" Text="{Binding CustomText, RelativeSource={
RelativeSource Self}, UpdateSourceTrigger=PropertyChanged}" CustomText="{Binding
TextForCustomTextBox, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Row="1" HorizontalAlignment="Center" Width="200" Height="50" />
Try setting your DataContext BEFORE the actual initialization so it is available when the form/control objects are created. If it can't find before, is that what may be causing the failed bindings.

Viewmodel object does not receive database source changes

New to WPF, MVVM, data binding, and Entity Framework, so apologies in advance.
I'm attempting to bind WPF controls to my database-generated model objects through a viewmodel. I'm able to change database values by typing in the textbox, but any direct changes to the database rows do not seem to fire off the PropertyChanged event. At least they are not reflected in my viewmodel objects. I've implemented iNotifyPropertyChanged on my Entity Framework generated classes thus:
public partial class GenGround : INotifyPropertyChanged
{
public double ClMax
{
get { return (double)this.clMax; }
set
{
this.clMax = (float)value;
MainWindow.db.SaveChanges();
OnPropertyChanged("ClMax");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string Property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(Property));
}
}
}
I have a listbox:
<DataTemplate x:Key="missionLegTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
<ListBox x:Name="missionList" SelectionChanged="missionList_SelectionChanged" Grid.ColumnSpan="2" ItemsSource="{Binding Mode=OneWay}" ItemTemplate="{DynamicResource missionLegTemplate}" />
private void MainWindow1_Loaded(object sender, RoutedEventArgs e)
{
this.missionList.ItemsSource = _CurrentMissionProfile.MissionLegs;
}
"MissionLegs" is an ObservableCollection of MissionLeg objects, attached to the database. The selected item of this listbox should tell the textboxes what properties to get and set. Textbox:
<TextBox x:Name="velocityBox" Text="{Binding Mode=TwoWay,Path=SelectedItem.Velocity, ElementName=missionList}" IsEnabled="False" />
As I said, this seems to write to the database, but when I make changes to the corresponding row in SSMS, nothing seems to happen. Ideas?

Binding a String to a richtextbox

I have a datagrid populated with "notes" and when a note is clicked I want the richtextbox to show the note.comments. But the Bindings isn't working.
public NoteDTO SelectedNote {get; set;}
public string stringNotes {get; set;}
public void OpenNote()
{
stringNotes = SelectedNote.Comments;
}
<DataGrid x:Name="NoteGrid" cal:Message.Attach="[Event MouseDoubleClick] = [Action OpenNote()]" ItemsSource="{Binding Notes}" SelectedItem="{Binding SelectedNote}"
<toolkit:RichTextBox Text="{Binding stringNotes, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
If I may get help please.
The main problem is that you're binding to a property that has no concept of change notifications; you're not implementing INotifyPropertyChanged. That being said, why not just bind the RichTextBox directly to the property off of NoteDTO:
<toolkit:RichTextBox Text="{Binding SelectedNote.Comments, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
The other option is to manually copy the comments between SelectedNote and stringNotes, then implement INotifyPropertyChanged, but this isn't ideal unless you want to have an intermediate property before propagating them to the NoteDTO object.
EDIT:
I noticed that your SelectedNote property will never notify the UI that it has changed, which will prevent bindings from working. Try something like the following:
public class MyClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if(this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private string selectedNote;
public string SelectedNote
{
get { return this.selectedNote; }
set
{
if (this.selectedNote == value)
return;
this.selectedNote = value;
this.OnPropertyChanged("SelectedNote");
}
}
}

Binding data to combobox in WPF

I am a beginner in programming, especially WPF. I have an application in WPF. I have changed connection to .sdf database from Entity Framework to SqlCeCommand. Unfortunatelly, before this I had the following code for binding a ComboBox.
<DockPanel Grid.Row="4">
<Button x:Name="LoadButton" Height="20" ToolTip="Choose setting name to load" Width="75" Padding="2,2,2,2" Margin="2,0,2,0" HorizontalAlignment="Left" VerticalAlignment="Center" Content="Load Settings" Command="{Binding LoadSettingsCommand}"/>
<ComboBox x:Name="LoadSettingsComboBox" ToolTip="Choose setting name to load" ItemsSource="{Binding Mode=OneWay, Path=Settings/}" SelectedValue="{Binding LoadSettingName, Mode=OneWayToSource}" SelectedValuePath="Name" Grid.Column="1" >
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment="Center" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DockPanel>
and:
List<Setting> _settings;
Settings = new CollectionView(_settings);
And it worked. After changing connection to DataBase there is no error, but ComboBox doesn't show any data. Before Setting class was generated by entity framework. Now, I made my own class Setting. What this class should implement? Can you help me?
Vote this answer if you find it helpful.
As per my understanding if you are using Setting as data object you need to store it into ObservableCollection<>. Use like this :
private ObservableCollection<Settings> _settingList = new ObservableCollection<Settings>();
public ObservableCollection<Settings> SettingList
{
get
{
return this._settingList;
}
set
{
if(value==null)
return;
this._settingList = value;
//OnPropertyChanged(()=>this.SettingList); //It is not required as ObservableCollection<> itself notifies on collection changed.
}
}
If you are implementing your own Setting class then you should implement INotifyPropertyChanged interface to bind properties with combobox item. Below is the code for your reference:
public class SettingsModel : INotifyPropertyChanged
{
#region INotifyPropertyChanded event Implementation
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged<TProperty>(Expression<Func<TProperty>> propertyExpression)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null == handler)
return;
if (null != propertyExpression)
{
var e = new PropertyChangedEventArgs(((MemberExpression)propertyExpression.Body).Member.Name);
handler(this, e);
}
}
public void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != PropertyChanged)
handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Above implementation gives you a method OnPropertyChanged(string propertyName). You need to call this method on "set" section of your each property in your class. Whenever property value gets changed it will notify to the DependencyProperty of control.
Hope this will help you.

Resources