将代码隐藏中定义的依赖属性通过Xaml绑定到UserControl的DataContext中的属性

时间:2011-02-25 19:46:18

标签: .net wpf user-interface binding

我想使用类似于找到的代码here.我遇到的问题是我想扩展它以允许XAML中设置的值使用{Binding PropertyOfViewModel},如下所示:

<local:TestControl>
  <local:TestControl.TestObject>
    {Binding PropertyOfViewModel}
  </local:TestControl.TestObject>
</local:TestControl>

问题是,它出现“无法转换”{Binding PropertyOfViewModel}“”的错误。 TestObject属性在视图的代码隐藏中定义为依赖项属性。

如果我可以让它工作,这将允许我在父控件中编写这样的代码:

<local:TestControl x:Name="myControl" DataContext="{Binding TCViewModel}" />

这意味着在UserControl中我还可以绑定到我的TCViewModel中公开的命令和其他项目,并且控件可以大部分是自包含的,并且所有消费者需要设置DataContext属性。


修改

这是整个控件:

<UserControl x:Class="MyProject.Views.AddClientView"
         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" 
         xmlns:Views="clr-namespace:MyProject.Views"
         Background="{StaticResource WindowBackgroundBrush}"
         mc:Ignorable="d">

<!-- Comment out from here
   <Views:AddClientView>
    <Views:AddClientView.RenderTransform>
        <ScaleTransform ScaleY="1" />
    </Views:AddClientView.RenderTransform>
    <Views:AddClientView.IsInAcceptDataMode>
        <Binding Path="IsInInputMode"/>
    </Views:AddClientView.IsInAcceptDataMode>
    <Views:AddClientView.ContentTemplate>
        <DataTemplate>
to here -->
            <Grid>
                <Label 
                    Height="25" 
                    Width="306"
                    HorizontalAlignment="Left" 
                    Margin="12,12,0,0" 
                    OverridesDefaultStyle="False" 
                    Style="{DynamicResource CalloutLabel}" 
                    VerticalAlignment="Top" Content="Company Name (Name of Organizational Unit)"/>

                <TextBox Height="23" Margin="12,41,12,0" VerticalAlignment="Top" TabIndex="1" />

                <Button 
                    Style="{DynamicResource LightButton}" 
                    Height="23" Width="75" 
                    HorizontalAlignment="Right" 
                    VerticalAlignment="Bottom" 
                    Margin="0,0,97,12" 
                    TabIndex="4">OK</Button>

                <Button 
                    Style="{DynamicResource LightButton}" 
                    Height="23" Width="75" 
                    HorizontalAlignment="Right" 
                    VerticalAlignment="Bottom" 
                    Margin="0,0,12,12" 
                    Command="{Binding Cancel}"
                    TabIndex="3">Cancel</Button>

                <CheckBox Content="Make Groups" Height="16" IsChecked="True" FlowDirection="RightToLeft" Margin="150,79,12,0" VerticalAlignment="Top" TabIndex="2" />

                <Rectangle Fill="{DynamicResource HeaderBarFill}" Height="5" Margin="0,0,0,0" Stroke="{x:Null}" VerticalAlignment="Bottom" />
            </Grid>
<!-- and here 
        </DataTemplate>
    </Views:AddClientView.ContentTemplate>
</Views:AddClientView>
to here-->

为了使用建议的代码进行编译,我不得不重新安排我的xaml,现在它在设计模式下都崩溃了Visual Studio,当我运行它时,我在{{1}上得到一个StackOverflow异常在Views Constructor中。


编辑2

这是将此UserControl放在窗口上的代码:

InitializeComponent();

有趣的是:如果我从Window中删除此代码,它会运行/编译好。如果我从View中删除所有<Views:AddClientView x:Name="AddClient" VerticalAlignment="Top" DataContext="{Binding AddClientVM}"> </Views:AddClientView> 类型代码,它也会运行正常。但是没有做我想要的,因为我无法将我的DP绑定到DataContext。

如果我将UserControl更改为以下内容,一切都编译得很好,我只是松开了代码隐藏依赖项属性的绑定:

<Views:AddClientView...>

代码隐藏依赖属性:

<UserControl 
    x:Class="Mage.Views.AddClientView"
    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" 
    xmlns:Views="clr-namespace:Mage.Views"
    Background="{StaticResource WindowBackgroundBrush}"
    mc:Ignorable="d"  d:DesignWidth="320" d:DesignHeight="145"
    x:Name="AddClientV"
    MaxHeight="145" MinHeight="145">

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState x:Name="Show">
                <VisualState.Storyboard>
                    <Storyboard>
                    <DoubleAnimation 
                            Storyboard.TargetProperty="RenderTransform.(ScaleTransform.ScaleY)" 
                            Storyboard.TargetName="AddClientV" 
                            From="0" 
                            To="1" 
                            Duration="0:0:1" />
                    </Storyboard>
                </VisualState.Storyboard>
            </VisualState>

            <VisualState x:Name="Hide">
                <VisualState.Storyboard>
                    <Storyboard>
                    <DoubleAnimation 
                        Storyboard.TargetProperty="RenderTransform.(ScaleTransform.ScaleY)" 
                        Storyboard.TargetName="AddClientV" 
                        From="1" 
                        To="0" 
                        Duration="0:0:1" />
                    </Storyboard>
                </VisualState.Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    <Views:AddClientView>
        <Views:AddClientView.RenderTransform>
            <ScaleTransform ScaleY="1" />
        </Views:AddClientView.RenderTransform>
        <Views:AddClientView.IsInAcceptDataMode>
            <Binding Path="IsInInputMode"/>
        </Views:AddClientView.IsInAcceptDataMode>
        <Views:AddClientView.ContentTemplate>
            <DataTemplate>
                <Grid>
                    <Label 
                        Height="25" 
                        Width="306"
                        HorizontalAlignment="Left" 
                        Margin="12,12,0,0" 
                        OverridesDefaultStyle="False" 
                        Style="{DynamicResource CalloutLabel}" 
                        VerticalAlignment="Top" Content="Company Name (Name of Organizational Unit)"/>

                    <TextBox Height="23" Margin="12,41,12,0" VerticalAlignment="Top" TabIndex="1" />

                    <Button 
                        Style="{DynamicResource LightButton}" 
                        Height="23" Width="75" 
                        HorizontalAlignment="Right" 
                        VerticalAlignment="Bottom" 
                        Margin="0,0,97,12" 
                        TabIndex="4">OK</Button>

                    <Button 
                        Style="{DynamicResource LightButton}" 
                        Height="23" Width="75" 
                        HorizontalAlignment="Right" 
                        VerticalAlignment="Bottom" 
                        Margin="0,0,12,12" 
                        Command="{Binding Cancel}"
                        TabIndex="3">Cancel</Button>

                    <CheckBox Content="Make Groups" Height="16" IsChecked="True" FlowDirection="RightToLeft" Margin="150,79,12,0" VerticalAlignment="Top" TabIndex="2" />

                    <Rectangle Fill="{DynamicResource HeaderBarFill}" Height="5" Margin="0,0,0,0" Stroke="{x:Null}" VerticalAlignment="Bottom" />
                </Grid>
            </DataTemplate>
        </Views:AddClientView.ContentTemplate>
    </Views:AddClientView>
</UserControl>

编辑3

所以我被告知基于XAML的绑定存在问题,我尝试转向代码隐藏,但我仍然无法让它工作。所以,我正在考虑这一点,以基于代码隐藏的方式将我的DependencyProperty绑定到ViewModel中的一个项目,该项目被指定给我的UserControl的DataContext。

1 个答案:

答案 0 :(得分:1)

如果我理解了所有内容,那么你需要的是一个标准的MVVM场景和标准绑定。

可以这样做:

<local:TestControl TestObject="{Binding PropertyOfViewModel}">
</local:TestControl>

或者像这样:

<local:TestControl>
  <local:TestControl.TestObject>
    <Binding Path="PropertyOfViewModel"/>
  </local:TestControl.TestObject>
</local:TestControl>

更新:回复您显示的UserControl代码...

您正在做的是将控件置于其自身内部,这显然会给您一个StackOverflow异常。 您无需在ContentTemplate内定义UserControl。您可以直接将内容作为子元素放置:

<UserControl 
    x:Class="Mage.Views.AddClientView"
    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" 
    xmlns:Views="clr-namespace:Mage.Views"
    Background="{StaticResource WindowBackgroundBrush}"
    mc:Ignorable="d"  d:DesignWidth="320" d:DesignHeight="145"
    x:Name="AddClientV"
    MaxHeight="145" MinHeight="145">

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState x:Name="Show">
                <VisualState.Storyboard>
                    <Storyboard>
                    <DoubleAnimation 
                            Storyboard.TargetProperty="RenderTransform.(ScaleTransform.ScaleY)" 
                            Storyboard.TargetName="AddClientV" 
                            From="0" 
                            To="1" 
                            Duration="0:0:1" />
                    </Storyboard>
                </VisualState.Storyboard>
            </VisualState>

            <VisualState x:Name="Hide">
                <VisualState.Storyboard>
                    <Storyboard>
                    <DoubleAnimation 
                        Storyboard.TargetProperty="RenderTransform.(ScaleTransform.ScaleY)" 
                        Storyboard.TargetName="AddClientV" 
                        From="1" 
                        To="0" 
                        Duration="0:0:1" />
                    </Storyboard>
                </VisualState.Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    <Views:AddClientView.RenderTransform>
            <ScaleTransform ScaleY="1" />
    </Views:AddClientView.RenderTransform>
    <Views:AddClientView.IsInAcceptDataMode>
            <Binding Path="IsInInputMode"/>
    </Views:AddClientView.IsInAcceptDataMode>

   <Grid>
      <Label 
        Height="25" 
        Width="306"
        HorizontalAlignment="Left" 
        Margin="12,12,0,0" 
        OverridesDefaultStyle="False" 
        Style="{DynamicResource CalloutLabel}" 
        VerticalAlignment="Top" Content="Company Name (Name of Organizational Unit)"/>

    <TextBox Height="23" Margin="12,41,12,0" VerticalAlignment="Top" TabIndex="1" />

    <Button 
        Style="{DynamicResource LightButton}" 
        Height="23" Width="75" 
        HorizontalAlignment="Right" 
        VerticalAlignment="Bottom" 
        Margin="0,0,97,12" 
        TabIndex="4">OK</Button>

    <Button 
        Style="{DynamicResource LightButton}" 
        Height="23" Width="75" 
        HorizontalAlignment="Right" 
        VerticalAlignment="Bottom" 
        Margin="0,0,12,12" 
        Command="{Binding Cancel}"
        TabIndex="3">Cancel</Button>

    <CheckBox Content="Make Groups" Height="16" IsChecked="True" FlowDirection="RightToLeft" Margin="150,79,12,0" VerticalAlignment="Top" TabIndex="2" />

    <Rectangle Fill="{DynamicResource HeaderBarFill}" Height="5" Margin="0,0,0,0" Stroke="{x:Null}" VerticalAlignment="Bottom" />
  </Grid>
</UserControl>