WPF: привязка данных - пользовательский контроль не ведет себя - PullRequest
2 голосов
/ 20 марта 2009

У меня маленькая проблема с привязкой данных. (У меня обычно есть ...)

Это ошибка, которую я получаю в окне вывода во время выполнения:

System.Windows.Data Error: 39 : BindingExpression path error: 'CurrentKlokke' property not found on 'object' ''UIKlokke' (Name='anaKlokke')'. BindingExpression:Path=CurrentKlokke; DataItem='UIKlokke' (Name='anaKlokke'); target element is 'UIKlokke' (Name='anaKlokke'); target property is 'klokke' (type 'Klokke')

'anaKlokke' является экземпляром 'UIKlokke', пользовательского элемента управления, представляющего аналоговые часы.

    <UserControl
        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:local="clr-namespace:Klokketrening"
        mc:Ignorable="d"
        x:Class="Klokketrening.UIKlokke"
        x:Name="UserControl"
        DataContext="{Binding RelativeSource={RelativeSource self}}"
        d:DesignWidth="400" d:DesignHeight="400">

        <UserControl.Resources>
            <ControlTemplate x:Key="clockTemplate">
                <Grid>
                    <Grid.Resources>
                        <local:TimeTilVinkel x:Key="hourToAngle"/>
                        <local:MinuttTilVinkel x:Key="minuteToAngle"/>
                    </Grid.Resources>
                    <Grid.LayoutTransform>
                        <ScaleTransform ScaleX="2" ScaleY="2" />
                    </Grid.LayoutTransform>
                    <Ellipse Width="108" Height="108" StrokeThickness="3">
                        <Ellipse.Stroke>
                            <LinearGradientBrush>
                                <GradientStop Color="LightBlue" Offset="0" />
                                <GradientStop Color="DarkBlue" Offset="1" />
                            </LinearGradientBrush>
                        </Ellipse.Stroke>
                    </Ellipse>


                    <Canvas Width="102" Height="102">
                        <Ellipse Width="8" Height="8" Fill="Black" Canvas.Top="46" Canvas.Left="46" />
                        <Rectangle x:Name="HourHand" Canvas.Top="26" Canvas.Left="48" Fill="Black" Width="4" Height="25">
                            <Rectangle.RenderTransform>
                                <RotateTransform x:Name="HourHand2" CenterX="2" CenterY="25" Angle="{Binding Converter={StaticResource hourToAngle}}" />                     
                            </Rectangle.RenderTransform>
                        </Rectangle>
                        <Rectangle x:Name="MinuteHand" Canvas.Top="16" Canvas.Left="49" Fill="Black" Width="2" Height="35">
                            <Rectangle.RenderTransform>
                                <RotateTransform CenterX="1" CenterY="35" Angle="{Binding Converter={StaticResource minuteToAngle}}" />
                            </Rectangle.RenderTransform>
                        </Rectangle>
                    </Canvas>
                </Grid>
            </ControlTemplate>
        </UserControl.Resources>
        <Grid>
            <Control Template="{StaticResource clockTemplate}" DataContext="{Binding klokke}" />
        </Grid> 
    </UserControl>

и код:

public partial class UIKlokke
{

    public Klokke klokke
    {
        get {return (Klokke)GetValue(UIKlokke.KlokkeProperty); }
        set { SetValue(UIKlokke.KlokkeProperty, value); } 
    }

    public static readonly DependencyProperty KlokkeProperty;

    public UIKlokke()
    {
        this.InitializeComponent();
    }

    static UIKlokke()
    {
        UIKlokke.KlokkeProperty = DependencyProperty.Register("klokke", typeof(Klokke), typeof(UIKlokke));
    }
}

Когда я использую этот usercontrol, я хочу связать свойство klokke'а usercontrols со свойством CurrentKlokke объекта Game.

<local:UIKlokke x:Name="anaKlokke" Grid.Column="0" Grid.Row="1" klokke="{Binding CurrentKlokke}"/>

CurrentKlokke является свойством зависимости.

    public Klokke CurrentKlokke
    {
        get { return (Klokke)GetValue(Game.CurrentKlokkeProperty); }
        set { SetValue(Game.CurrentKlokkeProperty, value);  }
    }
    public static readonly DependencyProperty CurrentKlokkeProperty;

    static Game()
    {
        Game.CurrentKlokkeProperty = DependencyProperty.Register("CurrentKlokke", typeof(Klokke), typeof(Game));
    }

Я установил DataContext для сетки, содержащей экземпляр UIKlokke, в коде:

        _game = new Game(Game.GameLevel.Easy, 10);
        gridGameUI.DataContext = _game;

Я привязываю источник элементов списка к другому свойству объекта Game, и он работает нормально.

Кто-нибудь может мне помочь с этим?

Ответы [ 2 ]

2 голосов
/ 20 марта 2009

Попробуйте удалить свойство Klokke из элемента управления UIKlokke и напрямую связать DataContext объекта anaKlokke с Klokke.

Кроме того, вам не нужно иметь элемент управления в сетке внутри элемента управления пользователя. Вы можете просто использовать UserControls.Template:

<UserControl ... DataContext="No needed its set on the game">
  <UserControl.Template>
    <ControlTemplate>
      <Grid>
        <!-- ... -->
      </Grid>
    </ControlTemplate>
  </UserControl.Template>
</UserControl>

Таким образом, DataContext устанавливается прямо через UserControl

Если вам нужен доступ к Klokke в коде позади, вы можете использовать

var klokke = DataContext as Klokke;
if (klokke == null) return;

// use klokke
0 голосов
/ 20 марта 2009

Не уверен насчет этого, я только начинаю с WPF. Но разве вы не должны использовать Path в привязке следующим образом:

<local:UIKlokke x:Name="anaKlokke"  
                Grid.Column="0" Grid.Row="1" 
                klokke="{Binding Path=CurrentKlokke}"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...