سؤال

I am having a problem with data binding in XAML. I am just learning WPF, and after two days of research, I came up with this code:

C++/CX:

namespace App1
{    
    class buttonColor {

    public:
        buttonColor(Windows::UI::Color c) { foreground = c; }

        Windows::UI::Color get() { return foreground; }

        void set(Windows::UI::Color c) { foreground = c; }

    private:
        Windows::UI::Color foreground;
    };
}

I call it with this:

MainPage::MainPage()
{
    InitializeComponent();

    buttonColor t(Windows::UI::Colors::Blue);
}

XAML:

<Page.Resources>
    <CollectionViewSource x:Key="buttonColor" />
</Page.Resources>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" DataContext="{StaticResource buttonColor}">

    <Button Content="Test" Foreground="{Binding Source=t}" />
</Grid>

This sort of works: it does change the foreground to a dull red, but I can't control the color change. Does anyone know why this is not changing to the colors I tell it in my C++/CX code?

Update:

I posted my full code on GitHub here: https://github.com/user2509848/wpf/tree/master. Right now, all I am getting is a linking error that _foreColorProperty cannot be found. If anyone knows what I am doing wrong, please let me know.

هل كانت مفيدة؟

المحلول

  • It's a common mistake to use a Color instead of a Brush.
  • And also you should remove Source= or replace it with Path=

So instead of

<Button Content="Test" Foreground="{Binding t}" />

write:

<Button Content="Test"/>
    <Button.Foreground>
        <SolidColorBrush Color="{Binding t}"/>
    </Button.Foreground>
</Button>

Edited

The reason you can't see the color changes, is your property does not notify the XAML about the changes.

In Header:

public:
static property Windows::UI::Xaml::DependencyProperty^ ForeColorProperty
{
     Windows::UI::Xaml::DependencyProperty^ get()
     {
          return _foreColorProperty;
     }
}
public:
property Windows::UI::Color^ ForeColor
{
     Windows::UI::Color^ get()
     {
          return (Windows::UI::Color^)GetValue(ForeColorProperty);
     }
     void set(Windows::UI::Color^ value)
     {
          SetValue(ForeColorProperty, value);
     }
}

In CPP:

DependencyProperty^ MainPage::_foreColorProperty = DependencyProperty::Register(
    "ForeColor",
    GetTypeName<Windows::UI::Color>(),
    GetTypeName<MainPage>(),
    ref new PropertyMetadata(nullptr));

Then use "{Binding ForeColor}" to bind to this property.

More info

DataContext value of each FrameworkElement is responsible for resolving the binding path. Which means in order to bind correctly you should first make sure DataContext has the correct value. DataContext always inherits its value from its parent which means if you set the DataContext of MainPage to something, DataContext of Button will be equal to it unless set explicitly.

e.g. When you say <Button Foreground="{Binding t}"> you mean to set the foreground of Button to Button.DataContext.t

In this example DataContext of Button is supposed to be equal to the current instance of MainPage because we defined _foreColorProperty for this parent type: GetTypeName<MainPage>()

DependencyProperty^ MainPage::_foreColorProperty = DependencyProperty::Register(
    "ForeColor",
    GetTypeName<Windows::UI::Color>(),
--> GetTypeName<MainPage>(),
    ref new PropertyMetadata(nullptr));

But that's not enough, You have to set it in the constructor of MainPage:

DataContext = this;

If we need another class as the ViewModel for the MainPage we should create another class and add these properties to it (and change GetTypeName() too) and then

MyViewModelClass* vm = new MyViewModelClass();
DataContext = vm;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top