we have a wpf-window with some textboxes and a datagrid.
the textboxes descripe a parent (class a) object and the datagrid lists a collection of "childs" (class b => not derived from class a).
the childs can inherit values from the parent.
for example if the parent (class a) has a property Foo then the child object (class b) has a property Nullable which can either override the value of the parent or inherit the value of the parent.
now the datagrid should display the value in gray (if it is inherited) or in black (if the user overrides the value in the grid cell).
Unfortunatly Binding to InheritedText doesnt work. Does someone have any idea?
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<UserControls:InheritedTextBoxControl
Text="{Binding Path=?}"
InheritedText="{Binding Path=?}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
Thanks in advance
Tobi
--UPDATE--
xaml of InheritedTextBoxControl:
<UserControl x:Class="Com.QueoMedia.CO2Simulationstool.WPF.Utils.UserControls.InheritedTextBoxControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Width="Auto"
Height="Auto"
Name="cnt">
<Grid x:Name="LayoutRoot"
Background="White">
<TextBox TextChanged="TextBoxTextChanged"></TextBox>
<TextBlock Name="inheritedText"
IsHitTestVisible="False"
Margin="4,0"
VerticalAlignment="Center"
Opacity="0.5"
FontStyle="Italic"></TextBlock>
</Grid>
CodeBehind:
public partial class InheritedTextBoxControl : UserControl {
private bool _isInherited;
public static readonly DependencyProperty InheritedTextProperty = DependencyProperty.Register("InheritedText", typeof(String), typeof(InheritedTextBoxControl), new PropertyMetadata(""));
public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(InheritedTextBoxControl), new PropertyMetadata(default(string)));
public InheritedTextBoxControl() {
InitializeComponent();
}
public string InheritedText {
get { return (string)GetValue(InheritedTextProperty); }
set {
SetValue(InheritedTextProperty, value);
inheritedText.Text = value;
}
}
private bool IsInherited {
get { return _isInherited; }
set {
_isInherited = value;
if (value) {
inheritedText.Opacity = 0.5;
} else {
inheritedText.Opacity = 0;
}
}
}
public string Text {
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
private void TextBoxTextChanged(object sender, TextChangedEventArgs e) {
if (((TextBox)sender).Text.Length > 0) {
IsInherited = false;
} else {
IsInherited = true;
}
Text = ((TextBox)sender).Text;
}
}
The problem is the setter of your InheritedText property. WPF won't call this setter when the property is set from XAML. See Checklist for Defining a Dependency Property, section Implementing the "Wrapper" for details.
You will have to update inheritedText.Text in a PropertyChangedCallback like this:
public static readonly DependencyProperty InheritedTextProperty =
DependencyProperty.Register(
"InheritedText", typeof(string), typeof(InheritedTextBoxControl),
new PropertyMetadata(string.Empty, InheritedTextChanged));
private static void InheritedTextChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
((InheritedTextBoxControl)d).inheritedText.Text = (string)e.NewValue;
}
public string InheritedText
{
get { return (string)GetValue(InheritedTextProperty); }
set { SetValue(InheritedTextProperty, value); } // only call SetValue here
}
If someone is interested in the solution:
we did it using a CellTemplate containing a CustomControl name MaskedTextbox that has three properties (MaskedText, Text, IsMaskTextVisible) and a CellEditingTemplate to override the data.
The values are bound to an InheritableValueViewModel.
Tobi
Related
This question already has answers here:
XAML binding not working on dependency property?
(1 answer)
Callback when dependency property recieves xaml change
(2 answers)
Closed 9 months ago.
I'm trying to make a user control in WPF (using xceed). I have a combobox and an integerUpDown.
A label should change its content when one of those changes its value. First label has just a simple binding to the integerUpDown, that's working. Visual Studio created OnPropertyChanged() and getters/setters automatically and I try to use it to bind my result to the second label but it's not working. Nothing happens.
This is my XAML:
<UserControl x:Class="WpfApp2.CardSelectionControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp2" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel Margin="5" Width="300" Height="400" Background="LightGray">
<TextBox Margin="5" AcceptsReturn="True" FontSize="20" Padding="5" Height="70">placeholding</TextBox>
<ComboBox SelectedIndex="{Binding SelectedIndex}" Background="Red" Margin="5">
<ComboBoxItem Content="card1"></ComboBoxItem>
<ComboBoxItem Content="card2"></ComboBoxItem>
</ComboBox>
<xctk:UIntegerUpDown Margin="5" x:Name="upDown" Value="{Binding Level}" ></xctk:UIntegerUpDown>
<Label Height="50" Content="{Binding Level}"></Label>
<Label Height="50" Content="{Binding Result}" ></Label>
</StackPanel>
</UserControl>
Code behind:
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace WpfApp2
{
public partial class CardSelectionControl : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int Level
{
get { OnPropertyChanged(); return (int)GetValue(LevelProperty); }
set
{
OnPropertyChanged();
SetValue(LevelProperty, value);
}
}
public int SelectedIndex
{
get { OnPropertyChanged(); return (int)GetValue(SelectedIndexProperty); }
set
{
OnPropertyChanged();
SetValue(SelectedIndexProperty, value);
}
}
public int Result
{
get { return (int)GetValue(ResultProperty); }
set { SetValue(ResultProperty, value); }
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (SelectedIndex == 0)
{ Result = Level * 2; }
else if (SelectedIndex == 1)
{ Result = Level * 3; }
}
public static readonly DependencyProperty ResultProperty =
DependencyProperty.Register("Result", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(20));
public static readonly DependencyProperty LevelProperty =
DependencyProperty.Register("Level", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(10));
public static readonly DependencyProperty SelectedIndexProperty =
DependencyProperty.Register("SelectedIndex", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(0));
public CardSelectionControl()
{
DataContext = this;
InitializeComponent();
}
}
}
I assume you expect your setters to get called, hence why you are calling OnPropertyChanged everywhere. They don't get called so your code won't be executed.
Instead, you can add a callback to your dependency properties so you know when the values get changed:
public static readonly DependencyProperty LevelProperty =
DependencyProperty.Register("Level",
typeof(int),
typeof(CardSelectionControl),
new PropertyMetadata(10, new PropertyChangedCallback(OnChanged)));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var cardSelectionControl = (CardSelectionControl)d;
cardSelectionControl.Recalculate();
}
I took the liberty of changing OnPropertyChanged to Recalculate, added a PropertyChangedCallback for the combobox as well and the entire code becomes:
public partial class CardSelectionControl : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int Level
{
get { return (int)GetValue(LevelProperty); }
set { SetValue(LevelProperty, value); }
}
public int SelectedIndex
{
get { return (int)GetValue(SelectedIndexProperty); }
set { SetValue(SelectedIndexProperty, value); }
}
public int Result
{
get { return (int)GetValue(ResultProperty); }
set { SetValue(ResultProperty, value); }
}
public void Recalculate()
{
if (SelectedIndex == 0)
Result = Level * 2;
else if (SelectedIndex == 1)
Result = Level * 3;
}
public static readonly DependencyProperty ResultProperty =
DependencyProperty.Register("Result", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(20));
public static readonly DependencyProperty LevelProperty =
DependencyProperty.Register("Level", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(10, new PropertyChangedCallback(OnChanged)));
public static readonly DependencyProperty SelectedIndexProperty =
DependencyProperty.Register("SelectedIndex", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(0, new PropertyChangedCallback(OnChanged)));
private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var cardSelectionControl = (CardSelectionControl)d;
cardSelectionControl.Recalculate();
}
public CardSelectionControl()
{
DataContext = this;
InitializeComponent();
}
}
I have a ListView in UWP which displays a list of custom controls CustomControl. Reading around I have seen that other users have face similar issues and their solution mostly revolved around setting the DataContext of their controls, but I cannot understand how I can do that in my example. In order to dynamically update the view I used DependencyProperties in my model which is the following:
public class DataObject : DependencyObject
{
public string Name
{
get { return (string)GetValue(nameProperty); }
set { SetValue(nameProperty, value); }
}
// Using a DependencyProperty as the backing store for name. This enables animation, styling, binding, etc...
public static readonly DependencyProperty nameProperty =
DependencyProperty.Register("Name", typeof(string), typeof(DataObject), new PropertyMetadata("Name"));
}
Then in my main page I implemented the following logic to change the Name of my third element:
public sealed partial class MainPage : Page
{
private readonly ObservableCollection<DataObject> dataList;
public MainPage()
{
this.InitializeComponent();
this.dataList = new ObservableCollection<DataObject>();
for (int i = 0; i < 5; i++)
{
DataObject dataObject = new DataObject();
dataObject.Name = "Item " + i.ToString();
this.dataList.Add(dataObject);
}
DataListView.ItemsSource = dataList;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var obj = dataList.ElementAt(2);
obj.Name = "Hello!";
}
}
The XAML for the main page is the following:
<Page
x:Class="ListViewTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:ListViewTest.Controls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<ListView Name="DataListView">
<ListView.ItemTemplate>
<DataTemplate>
<controls:CustomControl DisplayName="{Binding Name}"></controls:CustomControl>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Content="Button" HorizontalAlignment="Center" Height="92" Width="238"
Click="Button_Click"/>
</Grid>
</Page>
The custom control CustomControl is this:
namespace ListViewTest.Controls
{
public sealed partial class CustomControl : UserControl
{
public string DisplayName
{
get { return (string)GetValue(DisplayNameProperty); }
set {
SetValue(DisplayNameProperty, value);
DisplayText.Text = value;
}
}
// Using a DependencyProperty as the backing store for DisplayName. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DisplayNameProperty =
DependencyProperty.Register("DisplayName", typeof(string), typeof(CustomControl), new PropertyMetadata("DisplayText"));
public CustomControl()
{
this.InitializeComponent();
}
}
Its structure is very simple:
<Grid>
<Button Name="ClickButton" Content="Button" Margin="171,165,0,0" VerticalAlignment="Top"/>
<TextBlock Name="DisplayText" HorizontalAlignment="Center" TextWrapping="Wrap" VerticalAlignment="Center"/>
</Grid>
The problem is that when I click the button nothing happens and I am struggling to understand why.
DataObject shouldn't inherit from DependencyObject. It should be defined as a CLR object that implements INotifyPropertyChanged:
public class DataObject : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Also, the setter of the CLR wrapper for the dependency property in CustomControls should only set the value of the dependency property. You could set the value of the TextBlock using a PropertyChangedCallback:
public sealed partial class CustomControl : UserControl
{
public string DisplayName
{
get { return (string)GetValue(DisplayNameProperty); }
set { SetValue(DisplayNameProperty, value); }
}
public static readonly DependencyProperty DisplayNameProperty =
DependencyProperty.Register(nameof(DisplayName), typeof(string), typeof(CustomControl),
new PropertyMetadata("DisplayText", new PropertyChangedCallback(OnChanged)));
private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CustomControl customControl = (CustomControl)d;
d.DisplayText = e.NewValue as string;
}
public CustomControl()
{
this.InitializeComponent();
}
}
I am trying to use AttachedProperty in my AvalonDock, I want it to be part of LayoutAnchorable but PropertyChangedCallback never get called. i have binded AttachedPropert and i am getting the control over ViewModel ie: when binded property changes it trigger my ViewModel Property.
My AttachedProperty
public static readonly DependencyProperty IsCanVisibleProperty =
DependencyProperty.RegisterAttached("IsCanVisible", typeof(bool), typeof(AvalonDockBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(IsCanVisiblePropertyChanged)));
private static void IsCanVisiblePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
LayoutAnchorable control = d as LayoutAnchorable;
if (control != null)
{
control.IsVisible = (bool)e.NewValue;
}
}
public static void SetIsCanVisible(DependencyObject element, bool value)
{
element.SetValue(IsCanVisibleProperty, value);
}
public static bool GetIsCanVisible(DependencyObject element)
{
return (bool)element.GetValue(IsCanVisibleProperty);
}
XAML
<xcad:DockingManager>
<xcad:LayoutRoot >
<xcad:LayoutPanel Orientation="Horizontal" >
<xcad:LayoutAnchorablePane >
<xcad:LayoutAnchorable Title="Folder" behv:AvalonDockBehaviour.IsCanVisible="{Binding IsHideExplorer, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
<Views:ExplorerView DataContext="{Binding ExplorerViewModel}"/>
</xcad:LayoutAnchorable>
</xcad:LayoutAnchorablePane>
</xcad:LayoutPanel>
</xcad:LayoutRoot>
</xcad:DockingManager>
ViewModel Property
private bool _IsHideExplorer;
public bool IsHideExplorer
{
get { return _IsHideExplorer; }
set { _IsHideExplorer = value; NotifyPropertyChanged(); }
}
I have tried attaching the property to DockingManager the PropertyChangedCallback works. Any Help guys.
Did you already check the DataContext of your LayoutAnchorable? Maybe the DataContext is not passed down to it. In that case the Binding would not work and your DependencyProperty is not updated.
similar to my Labeled TextBox, which issues are resolved in:
Labeled TextBox in Windows Universal App
I got two issues in my Labeled Combobox, but first the Code:
Generic.xaml:
<Style TargetType="template:LabeledComboBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="template:LabeledComboBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="{TemplateBinding Label}" FontWeight="Bold" VerticalAlignment="Center" Margin="10,0" />
<ComboBox x:Name="PART_ComboBox" ItemsSource="{TemplateBinding ItemsSource}" SelectedIndex="{TemplateBinding SelectedIndex}" SelectedValue="{TemplateBinding SelectedValue}" SelectedValuePath="{TemplateBinding SelectedValuePath}" DisplayMemberPath="{TemplateBinding DisplayMemberPath}" VerticalAlignment="Center" Margin="20,0,10,0" Grid.Row="1" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
LabeledComboBox.cs:
[TemplatePart(Name = "PART_ComboBox", Type = typeof(ComboBox))]
public sealed class LabeledComboBox : Control, IParameterReturnable
{
public static readonly DependencyProperty LabelProperty = DependencyProperty.Register("Label", typeof(string), typeof(LabeledComboBox), new PropertyMetadata(""));
public string Label
{
get { return GetValue(LabelProperty).ToString(); }
set { SetValue(LabelProperty, value); }
}
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(object), typeof(LabeledComboBox), new PropertyMetadata(null));
public object ItemsSource
{
get { return GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty SelectedIndexProperty = DependencyProperty.Register("SelectedIndex", typeof(int), typeof(LabeledComboBox), new PropertyMetadata(default(int)));
public int SelectedIndex
{
get { return (int) GetValue(SelectedIndexProperty); }
set { SetValue(SelectedIndexProperty, value); }
}
public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register("SelectedValue", typeof(object), typeof(LabeledComboBox), new PropertyMetadata(null));
public object SelectedValue
{
get { return GetValue(SelectedValueProperty); }
set { SetValue(SelectedValueProperty, value); }
}
public static readonly DependencyProperty SelectedValuePathProperty = DependencyProperty.Register("SelectedValuePath", typeof(string), typeof(LabeledComboBox), new PropertyMetadata(default(string)));
public string SelectedValuePath
{
get { return GetValue(SelectedValuePathProperty).ToString(); }
set { SetValue(SelectedValuePathProperty, value); }
}
public static readonly DependencyProperty DisplayMemberPathProperty = DependencyProperty.Register("DisplayMemberPath", typeof(string), typeof(LabeledComboBox), new PropertyMetadata(default(string)));
public string DisplayMemberPath
{
get { return GetValue(DisplayMemberPathProperty).ToString(); }
set { SetValue(DisplayMemberPathProperty, value); }
}
private ComboBox _comboBox;
public LabeledComboBox()
{
this.DefaultStyleKey = typeof(LabeledComboBox);
}
public LabeledComboBox(List<Parameter> parameterList)
{
this.Label = parameterList[0].DisplayName ?? "";
this.ItemsSource = parameterList;
this.SelectedValuePath = "DefaultValue";
this.DisplayMemberPath = "DefaultValue";
this.SelectedIndex = 0;
this.DefaultStyleKey = typeof(LabeledComboBox);
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
_comboBox = GetTemplateChild("PART_ComboBox") as ComboBox;
if (_comboBox != null)
{
_comboBox.SelectionChanged += OnComboBoxSelectionChanged;
if (_comboBox.Items != null)
{
this.SelectedIndex = 0;
_comboBox.SelectedValue = _comboBox.Items[this.SelectedIndex];
}
}
}
private void OnComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.SelectedValue = _comboBox.SelectedValue;
}
public string GetKey()
{
return Label;
}
public string GetValue()
{
return SelectedValue.ToString();
}
}
It will be called in two different ways:
Dynamically in C#:
stackPanel.Add(new LabeledComboBox(parameterList));
Static in Xaml:
<templates:LabeledComboBox Label="Kategorien:" ItemsSource="{Binding ElementName=pageRoot, Path=FeedCategories}" DisplayMemberPath="Name" SelectedValuePath="Name" />
As I said before I got two issues with it:
How can I bind the SelectionChangedEvent to access it in Xaml || C#
As you can see, I try to preselect the first Item, which does not work and I don't know how to do it right
Thank you very much for all helpful and well meant answers in advance!
Instead of creating a custom control and recreating all needed dependency properties, I would suggest you use the Header and HeaderTemplate properties of the built in ComboBox, which will be displayed, just like in your LabeledComboBox, above the selection menu. Additionally the SelectionChanged event will be available.
So the usage in XAML would look like the following:
<ComboBox
DisplayMemberPath="Name"
Header="Kategorien:"
ItemsSource="{Binding ElementName=pageRoot, Path=FeedCategories}"
SelectedValuePath="Name"
SelectionChanged="OnSelectionChanged">
<ComboBox.HeaderTemplate>
<DataTemplate>
<TextBlock
Margin="10,0"
VerticalAlignment="Center"
FontWeight="Bold"
Text="{Binding}" />
</DataTemplate>
</ComboBox.HeaderTemplate>
</ComboBox>
But if you don't want to use the above method, to expose the selection changed event in your LabeledComboBox, add the following code:
private void OnComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.SelectedValue = _comboBox.SelectedValue;
this.RaiseSelectionChanged(e);
}
public event EventHandler<SelectionChangedEventArgs> SelectionChanged;
private void RaiseSelectionChanged(SelectionChangedEventArgs args)
{
if (SelectionChanged != null)
{
SelectionChanged(this, args);
}
}
Then you can use the created SelectionChanged event from XAML.
I have a simple WPF window with a TabItem containing a ComboBox with colors and a custom Canvas drawing a rectangle with that color. In my PaintCanvas I have a DependencyProperty like this:
class PaintCanvas : System.Windows.Controls.Canvas
{
public static readonly DependencyProperty PaintObjectProperty = DependencyProperty.Register(
"PaintObject", typeof(PaintObject), typeof(PaintCanvas), new PropertyMetadata(OnPaintObjectChanged));
public PaintObject PaintObject
{
get { return this.GetValue(PaintObjectProperty) as PaintObject; }
set
{
this.SetValue(PaintObjectProperty, value);
}
}
private static void OnPaintObjectChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PaintCanvas canvas = (PaintCanvas)d;
// Update stuff
canvas.InvalidateVisual();
}
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
if (PaintObject != null)
{
dc.DrawRectangle(new SolidColorBrush(PaintObject.Color), null, new Rect(0, 0, PaintObject.Width, PaintObject.Height));
}
}
}
The PaintObject dependency property is bound in xaml to its corresponding property in PaintViewModel:
<TabControl>
<TabItem DataContext="{Binding PaintViewModel}">
<StackPanel >
<ComboBox ItemsSource="{Binding Colors}" SelectedItem="{Binding Color}" />
<my:PaintCanvas Width="100" Height="100" PaintObject="{Binding PaintObject}" />
</StackPanel>
</TabItem>
</TabControl>
PaintViewModel is a property in the Window's ViewModel:
class MainViewModel
{
PaintViewModel paintViewModel;
public MainViewModel()
{
paintViewModel = new PaintViewModel();
}
public PaintViewModel PaintViewModel
{
get { return paintViewModel; }
}
...
}
The actual PaintViewModel:
class PaintViewModel : INotifyPropertyChanged
{
PaintObject paintObject;
ObservableCollection<Color> colors = new ObservableCollection<Color>();
Color currentColor;
public PaintObject PaintObject
{
get { return paintObject; }
set { paintObject = value; RaisePropertyChanged("PaintObject"); }
}
public ObservableCollection<Color> Colors
{
get { return colors; }
}
public Color Color
{
get { return currentColor; }
set {
currentColor = value;
RaisePropertyChanged("Color");
paintObject.Color = currentColor;
RaisePropertyChanged("PaintObject");
}
}
// Constructors and INotifyPropertyChanged stuff...
}
The TabItem seems to be correctly bound to the view model, because the color combobox works as it should. However, although the paint object is updated and RaisePropertyChanged("PaintObject") is called, the DependencyProperty in PaintCanvas is never updated. What am I doing wrong here??
I don't see that you change reference to PaintObject, you cahanged one of the properties of it(Color) and fire as PaintObject is changed, and since it is not, dependency property doesnt refresh
As a solution, you can add Color dependency property in the PaintCanvas, and bind Color to PaintObject.Color in xaml
<my:PaintCanvas Width="100" Height="100" PaintObject="{Binding PaintObject}" Color={Binding PaintObject.Color} />
And if you not forget to call NotifyPropertyChanged of Color property in PaintObject, PaintConvas Color property will be fired to be changed
I see some mess in your design, try to keep things simple