I am trying to send objects to an UserControl
, but I cannot figure what's wrong?
Here is my UserControl :
namespace VSTEEL.UserControls
{
/// <summary>
/// Interaction logic for UserControlListOperations.xaml
/// </summary>
public partial class UserControlListOperations : UserControl,INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string nomPropriete)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(nomPropriete));
}
public string MyString
{
get
{
return (string)GetValue(MyStringProperty);
}
set
{
SetValue(MyStringProperty, value); this.NotifyPropertyChanged("MyString");
}
}
public static DependencyProperty MyStringProperty =
DependencyProperty.Register(
nameof(MyString),
typeof(string),
typeof(UserControlListOperations),
new PropertyMetadata(MyStringPropertyChanged));
private static void MyStringPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
//var userControl = (UserControlMyString)obj;
// handle the new property value here
}
public static DependencyProperty ListOp1Property =
DependencyProperty.Register(
nameof(ListOp1),
typeof(IList<Operation>),
typeof(UserControlListOperations),
new PropertyMetadata(ListOp1PropertyChanged));
public IList<Operation> ListOp1
{
get
{
return (IList<Operation>)GetValue(ListOp1Property);
}
set
{
SetValue(ListOp1Property, value);this.NotifyPropertyChanged("ListOp1");
}
}
private static void ListOp1PropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var userControl = (UserControlListOperations)obj;
// handle the new property value here
}
public Contract Contract
{
get
{
return (Contract)GetValue(ContractProperty);
}
set
{
SetValue(ContractProperty, value); this.NotifyPropertyChanged("Contract");
}
}
public static DependencyProperty ContractProperty =
DependencyProperty.Register("Contract", typeof(Contract), typeof(UserControlListOperations));
private List<Operation> listOp2 { get; set; } = new List<Operation>( Global.GetListOperations());
public List<Operation> ListOp2 { get { return this.listOp2; } set { this.listOp2 = value; } }
public UserControlListOperations()
{
InitializeComponent();
this.DataContext = this;
}
static FrameworkPropertyMetadata propertyMetaData = new FrameworkPropertyMetadata
(
"UserControlListOperations",
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(TextProperty_PropertyChanged)
);
private static void TextProperty_PropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
}
}
}
And here is my main window, from which I am trying to open the UserControl :
<GridViewColumn Header="{x:Static p:Resources.Advancement}" Width="{Binding WidthColumnContractAdv, Mode=TwoWay}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Tag="{Binding}" MouseMove="mouseOverProgressionContractAss">
<Grid>
<views:UserControlListOperations
ListOp1 = "{Binding Path = ListOpAss}"
MyString="toto"/>
<!--SetListOp2 = "{Binding DataContext.ListOpAssTot}"/>-->
</Grid>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="{x:Static p:Resources.Advancement}" Width="{Binding WidthColumnContractAdv, Mode=TwoWay}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Tag="{Binding}" MouseMove="mouseOverProgressionContractAss">
<Rectangle Name="AFF_Track" Height="12" Stroke="black" StrokeThickness="1" Tag="{Binding ID}">
<Rectangle.Fill>
<MultiBinding Converter="{StaticResource :listOpToLinearGradientBrush}">
<Binding Path="ListOpAss" />
<Binding RelativeSource="{RelativeSource AncestorType={x:Type Fluent:RibbonWindow}}" Path="DataContext.ListOpAssTot" />
<Binding Source="0"/>
</MultiBinding>
</Rectangle.Fill>
<Rectangle.ToolTip>
<ContentControl Template="{StaticResource ToolTipOperations}"/>
</Rectangle.ToolTip>
</Rectangle>
<Rectangle Name="AFF_Track2" Height="12" Stroke="black" StrokeThickness="1" Tag="{Binding ID}">
<Rectangle.Fill>
<MultiBinding Converter="{StaticResource :listOpToLinearGradientBrush}">
<Binding Path="ListOpAss" />
<Binding RelativeSource="{RelativeSource AncestorType={x:Type Fluent:RibbonWindow}}" Path="DataContext.ListOpAssTot" />
<Binding Source="1"/>
</MultiBinding>
</Rectangle.Fill>
<Rectangle.ToolTip>
<ContentControl Template="{StaticResource ToolTipOperations}"/>
</Rectangle.ToolTip>
</Rectangle>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
My first GridViewColumn is the one opening the UserControl, but in debugging, I can se that SetValue(ListOp1Property, value);
is never launched, and that's what I cannot understand? (the UserControl is corrctly initialized)
I left the second column to check, that all is working fine without using UseControl (and it is working).
Here is my UserControl XAML : (I added a string MyString
, and it is corrctly set, not objects.
<UserControl x:Class="VSTEEL.UserControls.UserControlListOperations"
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:converters="clr-namespace:VSTEEL.Converters;assembly=MainLibrary"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:VSTEEL.UserControls"
mc:Ignorable="d"
>
<UserControl.Resources>
<converters:ListOpToLinearGradientBrush x:Key=":listOpToLinearGradientBrush" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Label Content="{Binding MyString}"/>
<Rectangle Grid.Row="1" Name="AFF_Track" Height="12" Stroke="black" StrokeThickness="1" Tag="{Binding ID}">
<Rectangle.Fill>
<MultiBinding Converter="{StaticResource :listOpToLinearGradientBrush}">
<Binding Path="ListOp1" />
<Binding Path="Contract" />
<Binding Source="0"/>
</MultiBinding>
</Rectangle.Fill>
</Rectangle>
<Rectangle Grid.Row="2" Name="AFF_Track2" Height="12" Stroke="black" StrokeThickness="1" Tag="{Binding ID}">
<Rectangle.Fill>
<MultiBinding Converter="{StaticResource :listOpToLinearGradientBrush}">
<Binding Path="ListOp1" />
<Binding Path="Contract" />
<Binding Source="0"/>
</MultiBinding>
</Rectangle.Fill>
</Rectangle>
</Grid>
</UserControl>
CodePudding user response:
Yould have to register the PropertyChangedCallback with PropertyMetadata that you pass as a fourth argument to the Register method. You should also use a more generic type for the property.
A correct dependency property implementation would look like this:
public static readonly DependencyProperty ListOp1Property =
DependencyProperty.Register(
nameof(ListOp1),
typeof(IList<Operation>), // or ICollection or IEnumerable
typeof(UserControlListOperations),
new PropertyMetadata(ListOp1PropertyChanged)); // here
public IList<Operation> ListOp1
{
get { return (IList<Operation>)GetValue(ListOp1Property); }
set { SetValue(ListOp1Property, value); }
}
private static void ListOp1PropertyChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var userControl = (UserControlListOperations)obj;
// handle the new property value here
}
Besides that, in order to bind to its own properties, the Bindings in the UserControl's XAML must have their source object to the control instance, e.g. by RelativeSource={RelativeSource AncestorType=UserControl}
.
When there ary many such Bindings, you can alternatively set the DataContext of the top level element in the control's XAML:
<Grid DataContext="{Binding
RelativeSource={RelativeSource AncestorType=UserControl}}">