1

I have a collection of Objects with dependencyproperties, and Observer patern as I feed realtime data in "AssetIHM" Object.

 public class assetVM: DependencyObject ,IObserver
{


    public assetVM(AssetIHM aihm) 
    {
        ObserverCollectionSingleton.ObserverCollectionInstance.Add(this);
        _aihm = aihm;
    }

    private string _assetname;
    public string assetname
    {
        get { return _assetname; }
        set
        {
            _assetname = value;
            SetValue(assetnameprop, value);
        }
    }
    public static readonly DependencyProperty assetnameprop =
    DependencyProperty.Register("assetnameprop",    typeof(string),typeof(assetVM), new UIPropertyMetadata(""));
    ...

I also have a UserControl, Which should display the information contained in the AssetVM object:

 public partial class AssetPanel : UserControl
{ 
    public assetVM Asset 
    {
        get
        {
            return (assetVM)GetValue(assetProperty);
        }
        set
        {
            SetValue(assetProperty, value);
        }

    }
    public static DependencyProperty assetProperty =    DependencyProperty.Register(
       "Asset", typeof(assetVM), typeof(AssetPanel), new   PropertyMetadata(null, new PropertyChangedCallback(OnCurrentItemChanged)));

    public AssetPanel(assetVM _Asset)
    {
        Asset = _Asset;
        this.DataContext = this;
        InitializeComponent();
        ...
    }

    public AssetPanel( )
    {
        this.DataContext = this;
        InitializeComponent();
        ...
    }
    ...

I my main windows, I have a ListBox,

<Window x:Class="ETRportfolio.MainWindow"        
    DataContext = "{Binding RelativeSource={RelativeSource Self}}"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:UserControls="clr-namespace:ETRportfolio"  
    Title="MainWindow" Height="1200" Width="1425">



<StackPanel HorizontalAlignment="Left" Height="1153" VerticalAlignment="Top" Width="1400" Margin="10,10,-18,0">

    <ListBox  x:Name="Gridview" Height="800"    >
         <ListBox.ItemTemplate>
            <DataTemplate>
                <UserControls:AssetPanel Asset="{Binding}" />
            </DataTemplate>
         </ListBox.ItemTemplate>
    </ListBox>
</StackPanel>

MY problem is that I would like to feed my Usercontrol with the data contained is the collection of AssetVM.

public partial class MainWindow : Window
{

    public static Dispatcher curDispatcher;

    public ObservableCollection<assetVM> Datas
    {
        get
        {
            return (ObservableCollection<assetVM>)curDispatcher.Invoke(
                       System.Windows.Threading.DispatcherPriority.DataBind,
                       (DispatcherOperationCallback)delegate { return GetValue(DataSProperty); },
                       DataSProperty);
        }
        set
        {
            curDispatcher.BeginInvoke(DispatcherPriority.DataBind,
                (SendOrPostCallback)delegate { SetValue(DataSProperty, value); },
                value);
        }
    }

    public readonly DependencyProperty DataSProperty = DependencyProperty.Register("DataS", typeof(ObservableCollection<assetVM>), typeof(MainWindow), new PropertyMetadata(null, new PropertyChangedCallback(OnCurrentItemChanged)));
    public MainWindow()
    {

        this.DataContext = this;
        curDispatcher = this.Dispatcher;
        Datas =new ObservableCollection<assetVM>();


        InitializeComponent();
        Gridview.ItemsSource = Datas; 
        addasset.addbtn.Click += onclik;
    }

When the AssetPanel constructor is created, it doesn't bind with My AssetVM datas. I always pass through the empty constructor.

How Can I do that in XAML?
I guess the problem is there:

ListBox.ItemTemplate>
            <DataTemplate>
                <UserControls:AssetPanel Asset="{Binding}" />
            </DataTemplate>
         </ListBox.ItemTemplate>

Thks!

Edit::

I removed this.DataContext = this;

In the UserControl constructor, but the UserControl Constructor called when a DataObject

assetVM

is added to the ObservableCollection Datas, used as datasource for the Listview, is this the empty constructor. but not:

 public AssetPanel(assetVM _Asset)
>     {
>         Asset = _Asset; 
>         InitializeComponent();
>         ValuationInfo.ItemsSource = new List<string> { "%", "Value" };
>         AVbox.ItemsSource = Enum.GetValues(typeof(AV)).Cast<AV>();
>     }

So it doesn't bind.

Edit2::

 private static void OnCurrentItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

            AssetPanel instance = (AssetPanel)d;
            instance.Asset = (assetVM)e.NewValue;
            return;
        }

It binds ! :)

Nevertheless, the Registered Dependency properties in the dataobject are not displayed.

This is my Assetpanel xaml:

<UserControl x:Class="ETRportfolio.AssetPanel" 
             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" 
             d:DesignHeight="152" d:DesignWidth="1400">
    <Grid  >
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Border BorderBrush="#FFDE6A6A" BorderThickness="1" Grid.Row="0" Grid.Column="0" Background="lightblue">
            <TextBlock x:Name="assetnamebox" TextWrapping="Wrap" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl }, Path = assetnameprop, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="15"/>
        </Border>
   ...

TextBlock x:Name="assetnamebox" TextWrapping="Wrap" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl }, Path = assetnameprop,

is not binding with assetVM.assetname VIA the DependencyProperty assetnameprop.

What is wrong there?

thks

Huh Lin
  • 13
  • 3
  • If `assetnameprop` is a public property in class `assetVM`, which is in the DataContext of the control, you should not set the RelativeSource of the internal binding. Just bind `Text={Binding assetnameprop}`. Two-way also doesn't make sense on a TextBlock. It can't edit the text. – Clemens May 21 '15 at 15:14
  • Probably also take your favourite WPF book, and carefully read the data binding chapters once more. – Clemens May 21 '15 at 15:15
  • Excellent! thks! I have to admit that I'm not used to xaml, but I did want to to this HMI not programaticaly. It Helped me a Lot! – Huh Lin May 21 '15 at 15:23

1 Answers1

1

Setting a UserControl's DataContext to itself, as done in your constructors by the statements

this.DataContext = this;

effectivly disables binding to properties of inherited DataContexts, like in

<ListBox.ItemTemplate>
    <DataTemplate>
        <UserControls:AssetPanel Asset="{Binding}" />
    </DataTemplate>
</ListBox.ItemTemplate>

where the binding source is the inherited DataContext of the ListBoxItems, i.e. an assetVM instance.

Remove the DataContext assignment from your UserContr's constructors.

Clemens
  • 123,504
  • 12
  • 155
  • 268
  • I removed it, but the UserControl Constructor called when a DataObject assetVM is added to the ObservableCollection Datas, used as datasource for the Listview, is this the empty constructor. but not: public AssetPanel(assetVM _Asset) { Asset = _Asset; InitializeComponent(); ValuationInfo.ItemsSource = new List { "%", "Value" }; AVbox.ItemsSource = Enum.GetValues(typeof(AV)).Cast(); } So it doesn't bind. – Huh Lin May 21 '15 at 12:28
  • You only need the parameterless constructor. The other one is not necessary, and never used anywhere. The `Asset` property is set by the binding, you don't need to do that in a constructor or anywhere else. – Clemens May 21 '15 at 12:33
  • It is always setted at null in may case. – Huh Lin May 21 '15 at 12:36
  • My Mistake, It binds the AssetVM to the Usercontrol, but the usercontrol elements don't bind with the dependencyproperties of the dataobject. – Huh Lin May 21 '15 at 12:46
  • the AssetVM object being binded to the Usercontrol, I'm trying to bing the dataobject properties to the different control within the user control. It is not updating, as if the event isn't raised by the dispatcher. What Am I doing wrong? – Huh Lin May 21 '15 at 15:06
  • Also the property Asset needs to havec the same name that the registereddependency, "Asset", Otherwise it is not binding. Is that normal? – Huh Lin May 21 '15 at 15:08