views:

78

answers:

6

Hello,

i can't get this binding working in XAML.

Binding in c# works:

public partial class myControl : UserControl
{
    // get singleton instance
    InfoPool Info = InfoPool.Info;

    public myControl()
    {
        InitializeComponent();

        // Test Binding
        Binding bind = new Binding();
        bind.Source = this.Info;
        bind.Path = new PropertyPath("Time");
        txtInfoTime.SetBinding(TextBlock.TextProperty, bind);
    }
}

Binding in XAML not:

<TextBlock x:Name="txtInfoTime" Text="{Binding Path=Time, Source=Info}" />

Path and Source are the same, so where is my mistake?

Thx Rob

+3  A: 

You can't translate it to XAML with the exact same properties, because there is no way to reference this.Info directly. However, you can achieve the same result by setting a RelativeSource :

<TextBlock x:Name="txtInfoTime" Text="{Binding Path=Info.Time, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:myControl}}}" />
Thomas Levesque
Thanks for your answer, but i will use the other solution.
Robert Vernunft
A: 

You need to set the DataContext.

You can just add:

DataContext = Info

after

InitializeComponent();

And change XAML to:

<TextBlock x:Name="txtInfoTime" Text="{Binding Time}" />
Chris Persichetti
If he does that, EVERYTHING in the UserControl will have Info as the DataContext, and there will be no way to bind to something else...
Thomas Levesque
Good to know. Thanks :)
Chris Persichetti
So this kind of binding is easier I think, cause in don't need to bind to others in this control
Robert Vernunft
A: 

You need to set the DataContext of your UserControl

1-Xaml

<Grid>
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Name">

        </TextBlock>
        <Separator Width="10" Opacity="0">

        </Separator>
        <TextBox Name="txtName" Width="100"  Text="{Binding Name}"></TextBox>
    </StackPanel>
</Grid>

2- Code

public partial class Window1 : Window { public Window1() { InitializeComponent();

        InfoPool info = new InfoPool();
        info.Name = "Saurabh";
        this.DataContext = info;

    }
}

public class InfoPool
{
    public string Name { get; set; }
}
saurabh
+1  A: 

Since InfoPool is a singleton instance i would recommend the following:

<TextBlock x:Name="txtInfoTime" Text="{Binding Path=Time, Source={x:Static ns:InfoPool.Info}}"/>

Where ns is the xaml-alias for the namespace in which InfoPool is defined. No need to mess up your DataContext this way.

Bubblewrap
A: 

Based on your answers I solved the Problem like described below. I post it, because i guess that other beginners in WPF could find it useful.

I have singleton class (InfoPool.cs) wich implements INotifyChangedProperty. It's used to provide appwide bindable properties. This class is used by an ObjectDataProvider in App.xaml. So it's very "easy" to bind to a property

InfoPool.cs (the Singleton code is from http://csharpindepth.com/Articles/General/Singleton.aspx 5th Version. I changed the Instance Property to GetInstance() Method, because the OPD needs an Method)

public sealed class InfoPool : INotifyPropertyChanged
{
    InfoPool()
    {
    }

    public static InfoPool GetInstance()
    {
        return Nested.instance;
    }

    class Nested
    {
        static Nested()
        {
        }

        internal static readonly InfoPool instance = new InfoPool();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, e);
        }
    }

    private String strProp = "default String";
    private Double dblProp = 1.23456;

    public String StrProp
    {
        get { return strProp; }
        set 
        { 
            strProp = value;
            OnPropertyChanged(new PropertyChangedEventArgs("StrProp"));
        }
    }

    public Double DblProp
    {
        get { return dblProp; }
        set 
        { 
            dblProp = value;
            OnPropertyChanged(new PropertyChangedEventArgs("DblProp"));
        }
    }

The ObjectDataProvider in App.xaml

<Application.Resources>
    <ResourceDictionary>
        <ObjectDataProvider x:Key="OPDInfo" ObjectType="{x:Type local:InfoPool}" MethodName="GetInstance" d:IsDataSource="True"/>
    </ResourceDictionary>
</Application.Resources>

An here are 2 ways to bind to the OPD

<StackPanel>
    <TextBlock x:Name="tbprop1" Text="{Binding Path=StrProp, Source={StaticResource OPDInfo}}" />
    <TextBlock x:Name="tbprop2" Text="{Binding DblProp}" ToolTip="{Binding StrProp}" DataContext="{StaticResource OPDInfo}" />
</StackPanel>

That's it. Please comment, cause I'm new to this ;-)

Robert Vernunft
A: 

If you leave your singleton instance accessor as a property you don't need an ObjectDataProvider. You can just use the static instance directly.

<StackPanel>
<TextBlock x:Name="tbprop1" 
    Text="{Binding Path=StrProp, Source={x:Static local:InfoPool.Instance}}" /> 
</StackPanel>
grantnz
Just noticed that BubbleWrap has already given this info.
grantnz