Reputation: 4534
I'm trying to do a simple OneWay binding for a user control, but I honestly don't understand why some parts aren't working. To be simple, I created a WPF standard UserControl with some dependency properties. In my main window, I hide/display the UserControl depending of some events, and I bound the properties to my main window viewmodel data. However, doing that makes NOT my UserControl refreshing for SOME parts. For exampl, I have a SearchString dependency property on my UserControl :
public static readonly DependencyProperty SearchStringProperty = DependencyProperty.Register("SearchString",
typeof(string), typeof(DisplayMailView), new UIPropertyMetadata(null));
public string SearchString
{
get { return (string)GetValue(SearchStringProperty); }
set
{
SetValue(SearchStringProperty, value);
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("SearchString"));
}
var loFinds = richEditControl1.Document.FindAll(SearchString, SearchOptions.WholeWord);
foreach (var find in loFinds)
{
var oDoc = find.BeginUpdateDocument();
var oChars = oDoc.BeginUpdateCharacters(find);
oChars.BackColor = System.Drawing.Color.Yellow;
oDoc.EndUpdateCharacters(oChars);
find.EndUpdateDocument(oDoc);
}
}
}
This one in UserControl is bound to the SearchString member of my main Window viewmodel
<local:DisplayMailView SearchString="{Binding DataContext.SearchString, RelativeSource={RelativeSource AncestorType={x:Type Window}}, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True,NotifyOnTargetUpdated=True,Mode=TwoWay}"/>
On my ViewModel :
public string SearchString
{
get
{
return _searchString;
}
set
{
_searchString = value;
if (!string.IsNullOrWhiteSpace(value))
DataGridService.FocusFirstRow();
RaisePropertyChanged();
}
}
I put a break point into the set of my SearchString in my main window viewmodel, the value is set. However, when I put a breakpoint into the set of my SearchString on the UserControl, it never fire ?
Also, the dataContext of my UserControl is set :
(this.Content as FrameworkElement).DataContext = this;
I precise that my UserControl constructor is only called one time at launch, the other things must be dynamically refresh depending on user actions.
Does someone have an idea ? I have no errors in output window Thanks
Upvotes: 1
Views: 3349
Reputation: 4978
This is a common misconception. When a DependencyProperty's value changes, the code in its CLR property's set
is not executed. You need to use a PropertyChanged callback if you want to execute some code whenever the property value changes.
Your UserControl code should look like this, instead:
public static readonly DependencyProperty SearchStringProperty =
DependencyProperty.Register(
"SearchString",
typeof(string),
typeof(DisplayMailView),
new UIPropertyMetadata(null, OnSearchStringChanged));
// This sets OnSearchStringChanged as the PropertyChanged callback
public string SearchString
{
get { return (string)GetValue(SearchStringProperty); }
set
{
SetValue(SearchStringProperty, value);
// Any code you put here won't be executed
// when the DependencyProperty value changes
}
}
private static void OnSearchStringChanged(object sender, DependencyPropertyChangedEventArgs e)
{
// This part is not needed, DependencyProperties already
// notify of their changes automatically
//if (PropertyChanged != null)
//{
// PropertyChanged(this, new PropertyChangedEventArgs("SearchString"));
//}
var control = sender as DisplayMailView;
var loFinds = control.richEditControl1.Document.FindAll(SearchString, SearchOptions.WholeWord);
foreach (var find in loFinds)
{
var oDoc = find.BeginUpdateDocument();
var oChars = oDoc.BeginUpdateCharacters(find);
oChars.BackColor = System.Drawing.Color.Yellow;
oDoc.EndUpdateCharacters(oChars);
find.EndUpdateDocument(oDoc);
}
}
Upvotes: 6