WPF将UserControl绑定到MainWindow作为父级失败

时间:2015-05-06 15:28:45

标签: c# wpf xaml

我是XAML数据绑定的新手,我陷入了这种境地。我正在使用Mahapps MetroWindow。

假设我有一个名为usrctrl_Camera_Control的UserControl。我有一个简单的按钮。 C#代码如下所示。

namespace TA141501005
{
public partial class usrctrl_Camera_Control : UserControl
{      
    public usrctrl_Camera_Control()
    {        
        this.DataContext = this;
        InitializeComponent();
    }
}

XAML如下所示

<UserControl
         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:Custom="http://metro.mahapps.com/winfx/xaml/controls" xmlns:local="clr-namespace:TA141501005" x:Class="TA141501005.usrctrl_Camera_Control"
         mc:Ignorable="d" 
         d:DesignHeight="768" d:DesignWidth="1366" Background="#FF2B2B2B" Height="738" Width="1336">
<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Resources/Icons.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>
<Grid>     
    <Button x:Name="btn_Test" Content="Button" Grid.Column="1" HorizontalAlignment="Left" Margin="472,59,0,0" VerticalAlignment="Top" Width="75" Grid.RowSpan="2" IsEnabled="{Binding Path=IsNyetEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}}" />
</Grid>

MainWindow的C#代码如下所示。

namespace TA141501005
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>

public partial class MainWindow : MetroWindow
{
    usrctrl_Camera_Control usrctrl_camera_control;
    public bool IsNyetEnabled { get; set; }
    public MainWindow()
    {
        IsNyetEnabled = false;            
        this.DataContext = this;
        InitializeComponent();      
        usrctrl_camera_control = new usrctrl_Camera_Control();
    }
}

}

以及MainWindow的XAML代码如下所示。

    <Controls:MetroWindow x:Class="TA141501005.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
    Title="Macromium System Control V1.0ES - TA141501005 [Engineering Sample]" Height="768" Width="1366" Background="#FF2B2B2B" ScrollViewer.VerticalScrollBarVisibility="Disabled" ResizeMode="NoResize" WindowStyle="ThreeDBorderWindow" WindowStartupLocation="CenterScreen" IsMinButtonEnabled="False" IsWindowDraggable="False" ShowMaxRestoreButton="False" ShowMinButton="False" ShowSystemMenuOnRightClick="False" IconOverlayBehavior="Flyouts">
<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Resources/Icons.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>

<Grid>
    <Button x:Name="btn_test" Content="Button" HorizontalAlignment="Left" Margin="589,590,0,0" VerticalAlignment="Top" Width="75" IsEnabled="{Binding IsNyetEnabled}"/>
</Grid>

我想将usrctrl_Camera_Control中的btn_test中的属性IsEnabled和MainWindow中的btn_test绑定到MainWindow中的IsNyetEnabled。在MainWindow中执行InitializeComponent()之前,我将IsNyetEnabled设置为false。

MainWindow中的btn_test.IsEnabled与MainWindow中的IsNyetEnabled之间的绑定完美无瑕。 MainWindow中的btn_test不再启用。 (我知道,我需要实现INotifyPropertyChanged以通知subriber是否有任何更改但是现在,为了简单起见,请保持原样)。

但是,usrctrl_Camera_Control中的btn_test.IsEnabled与MainWindow中的IsNyetEnabled之间的绑定失败。我使用过Visual Studio&#34;创建数据绑定&#34;向导但它在编译时总是返回错误。

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='TA141501005.MainWindow', AncestorLevel='1''. BindingExpression:Path=IsNyetEnabled; DataItem=null; target element is 'Button' (Name='btn_Test'); target property is 'IsEnabled' (type 'Boolean')

你有什么建议吗?我没有运气就试了一整天。 有没有办法访问父datacontext而不删除this.Datacontext = this? 期待您的建议和解释。 非常感谢你。

编辑。 我通过Flyout显示我的UserControl。

Window parentWindow = Window.GetWindow(this);
object obj = parentWindow.FindName("mainFlyout");
Flyout flyout = (Flyout) obj;  
flyout.Content = new SomeFlyOutUserControl();
flyout.IsOpen = !flyout.IsOpen;

3 个答案:

答案 0 :(得分:0)

我建议你使用DependencyProperty

 public static readonly DependencyProperty IsButtonEnabledProperty = DependencyProperty.Register(
            "IsButtonEnabled", typeof(bool), typeof(UserControl1), new PropertyMetadata(default(bool)));

        public bool IsButtonEnabled
        {
            get { return (bool)GetValue(IsButtonEnabledProperty); }
            set { SetValue(IsButtonEnabledProperty, value); }
        } 

//此处将您的UserControl重命名为测试

 <Grid>     
        <Button x:Name="btn_Test" Content="Button" Grid.Column="1" HorizontalAlignment="Left" Margin="472,59,0,0" VerticalAlignment="Top" Width="75" Grid.RowSpan="2" IsEnabled="{Binding Path=IsButtonEnabled, ElementName=Test}"}" />
    </Grid>

答案 1 :(得分:0)

IsNyetEnabled上创建MainForm属性作为依赖项属性。这是mechanism that will propagate changes in WPF

示例:

public static readonly DependencyProperty IsNyetEnabledProperty = 
    DependencyProperty.Register("IsNyetEnabled", typeof(bool), 
    typeof(MainWindow),new FrameworkPropertyMetadata(false));

public bool IsNyetEnabled
{
    get { return (bool)GetValue(MainWindow.IsNyetEnabled); }
    set { SetValue(MainWindow.IsNyetEnabled, value); }
}

为此,您可以直接绑定Button中的MainWindow

对于UserControl虽然我们必须添加一个垫片,因为UserControl在创建它时无法找到祖先。 在您的UserControl上创建,例如Moez发布了另一个DependencyProperty

public static readonly DependencyProperty IsButtonEnabledProperty = 
    DependencyProperty.Register("IsButtonEnabled", typeof(bool), 
    typeof(usrctrl_Camera_Control),new FrameworkPropertyMetadata(false));

public bool IsButtonEnabled
{
    get { return (bool)GetValue(usrctrl_Camera_Control.IsButtonEnabledProperty); }
    set { SetValue(usrctrl_Camera_Control.IsButtonEnabledProperty, value); }
}

UserControl按钮IsEnabled属性绑定到该属性。

现在作为最后一步,我们将在您创建UserControl时连接两个依赖关系属性。

<local:usrctrl_Camera_Control x:Name="yourControl" ...Whatever else... IsButtonEnabled="{Binding Path=IsNyetEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}} />

现在应该可以了。

答案 2 :(得分:0)

正如@Frank J建议的那样,我修改了他的最后一步。 我在运行时创建usercontrol,而不是从XAML创建。因此,最后一步看起来就是这样。

 usrctrl_camera_control = new usrctrl_Camera_Control();
 Binding b = new Binding("IsNyetEnabled");
 b.Source = this;
 b.Mode = BindingMode.OneWay;
 usrctrl_camera_control.SetBinding(usrctrl_Camera_Control.IsButtonEnabledProperty, b);

非常感谢..我希望对那些与我有同样问题的人有用。