Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF链结合_C#_Wpf_Xaml_User Controls - Fatal编程技术网

C# WPF链结合

C# WPF链结合,c#,wpf,xaml,user-controls,C#,Wpf,Xaml,User Controls,我想这样做一个链绑定:在一个具有类似dependencyproperty的窗口中有一个具有dependencyproperty的usercontrol。我想将usercontrol的dependencyproperty绑定到窗口的dependencyproperty 我创建了一个示例项目来演示我的问题: UserControl1 XAML: <UserControl x:Class="WpfApplication1.UserControl1" xmlns="htt

我想这样做一个链绑定:在一个具有类似dependencyproperty的窗口中有一个具有dependencyproperty的usercontrol。我想将usercontrol的dependencyproperty绑定到窗口的dependencyproperty

我创建了一个示例项目来演示我的问题:

UserControl1 XAML:

<UserControl x:Class="WpfApplication1.UserControl1"
             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" 
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300" DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <Label Content="{Binding Caption}"/>
    </Grid>
</UserControl>
主窗口XAML:

<Window xmlns:WpfApplication1="clr-namespace:WpfApplication1"  x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Label Content="{Binding Caption, Mode=OneWay}"/>
        <WpfApplication1:UserControl1 x:Name="uc" Caption="{Binding Caption, Mode=OneWay}"  Grid.Row="1"/>
    </Grid>
</Window>
问题是,当我将标题设置为“XXX”(窗口的)时,我希望它也通知usercontrol并更新其标题,但它没有。我希望尽可能避免附加依赖属性和代码隐藏。有什么想法吗


感谢您的努力。

问题在于您的绑定。默认情况下,绑定在控件的DataContext属性上查找属性。每个绑定都有一个源,在您的例子中,它是控件的DataContext属性。因此,您的绑定将计算为DataContext.Caption。您真正想要的是生成绑定的源,即具有Caption属性的窗口。因此,按如下所示更改代码。我在我的机器上测试了它,它正常工作了。记住初始化窗口的标题属性

新的:


新的:



问题在于您的绑定。默认情况下,绑定在控件的DataContext属性上查找属性。每个绑定都有一个源,在您的例子中,它是控件的DataContext属性。因此,您的绑定将计算为DataContext.Caption。您真正想要的是生成绑定的源,即具有Caption属性的窗口。因此,按如下所示更改代码。我在我的机器上测试了它,它正常工作了。记住初始化窗口的标题属性

新的:


新的:



您可以创建一个用户控件,其内容如下:

<UserControl x:Class="ChainBinding.CaptionGuy"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             >
    <Grid>
            <Label Name="CaptionLabel"/>
    </Grid>
</UserControl>
然后您可以在WPF应用程序中部署它,如下所示

    #region Caption (DependencyProperty)
    public string Caption
    {
        get { return (string)GetValue(CaptionProperty); }
        set { SetValue(CaptionProperty, value); }
    }
    public static readonly DependencyProperty CaptionProperty =
        DependencyProperty.Register("Caption", typeof(string), typeof(CaptionGuy),
          new PropertyMetadata{PropertyChangedCallback = CaptionChanged});
    private static void CaptionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        CaptionGuy cg = d as CaptionGuy;
        if (cg != null && e.NewValue!=null)
        {
            cg.CaptionLabel.Content = e.NewValue.ToString();
        }
    }
    #endregion
<Grid>
    <chainBinding:CaptionGuy Caption="{Binding VmCaption}"/>
</Grid>
public class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
        DispatcherTimer dt = new DispatcherTimer(new TimeSpan(0,0,0,5), DispatcherPriority.Normal,
            delegate
            {
                VmCaption = DateTime.Now.ToString("G");
            }, dispatcher);
        dt.Start();
    }
    private string _vmCaption;
    public string VmCaption
    {
        [DebuggerStepThrough]
        get { return _vmCaption; }
        [DebuggerStepThrough]
        set
        {
            if (value != _vmCaption)
            {
                _vmCaption = value;
                OnPropertyChanged("VmCaption");
            }
        }
    }
    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion
}
这个例子只是每5秒更新一次标题


当然,这个答案使用了对dependency属性的回调,但这是一个环境实用性胜过声明性编程的问题。

您可以创建一个用户控件,如下所示

<UserControl x:Class="ChainBinding.CaptionGuy"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             >
    <Grid>
            <Label Name="CaptionLabel"/>
    </Grid>
</UserControl>
然后您可以在WPF应用程序中部署它,如下所示

    #region Caption (DependencyProperty)
    public string Caption
    {
        get { return (string)GetValue(CaptionProperty); }
        set { SetValue(CaptionProperty, value); }
    }
    public static readonly DependencyProperty CaptionProperty =
        DependencyProperty.Register("Caption", typeof(string), typeof(CaptionGuy),
          new PropertyMetadata{PropertyChangedCallback = CaptionChanged});
    private static void CaptionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        CaptionGuy cg = d as CaptionGuy;
        if (cg != null && e.NewValue!=null)
        {
            cg.CaptionLabel.Content = e.NewValue.ToString();
        }
    }
    #endregion
<Grid>
    <chainBinding:CaptionGuy Caption="{Binding VmCaption}"/>
</Grid>
public class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
        DispatcherTimer dt = new DispatcherTimer(new TimeSpan(0,0,0,5), DispatcherPriority.Normal,
            delegate
            {
                VmCaption = DateTime.Now.ToString("G");
            }, dispatcher);
        dt.Start();
    }
    private string _vmCaption;
    public string VmCaption
    {
        [DebuggerStepThrough]
        get { return _vmCaption; }
        [DebuggerStepThrough]
        set
        {
            if (value != _vmCaption)
            {
                _vmCaption = value;
                OnPropertyChanged("VmCaption");
            }
        }
    }
    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion
}
这个例子只是每5秒更新一次标题



当然,这个回答使用依赖属性的回调,但是这是一个间接的实用性胜过声明性编程的问题。

在用户控件的DP声明中,您是否考虑挂起属性更改的回调?这应该会带来您所追求的行为。我有这个想法,但我追求的是一个解决方案,如果有代码隐藏的话,那么代码就更少了。关于数据上下文冲突,请参见下面Kess的回答。但以依赖项属性中的三行代码为代价,您正在创建一个Xaml的matryoshka,而没有实际回报。@GarryVass我想我最终会同意您的建议,如果您将其作为答案编写,我会将其标记为已接受。@GarryVass Sure:。。。我只是想关闭这个问题并给予您信任。在用户控件的DP声明中,您是否考虑挂起属性更改的调用?这应该会带来您所追求的行为。我有这个想法,但我追求的是一个解决方案,如果有代码隐藏的话,那么代码就更少了。关于数据上下文冲突,请参见下面Kess的回答。但以依赖项属性中的三行代码为代价,您正在创建一个Xaml的matryoshka,而没有实际回报。@GarryVass我想我最终会同意您的建议,如果您将其作为答案编写,我会将其标记为已接受。@GarryVass Sure:。。。我只想结束这个问题,给你一个积分。服务的所有部分:)及时编辑会给你一个10分,否则会受到影响!使用Xaml的按钮:)感谢您的回答,我刚刚尝试了它,但不幸的是它似乎没有帮助-设置将标签的内容设置为其(RelativeSource Self)属性标题,该标题不存在(或者我错了吗?)。和Caption=“{Binding Path=Caption,RelativeSource={RelativeSource Mode=Self},Mode=OneWay}”将usercontrol的Caption属性设置为其自己的属性Caption,使其无效(或者我错了吗?)。然而,我可能误解了一些事情……我已经更新了答案。如果用户控件位于主窗口上,则需要从可视树中查找属性。上述解决方案应该有效。谢谢。我已经在Window.xaml中将datacontext设置为Window-在。。。同样,在用户控件中,这取决于您正在做什么。但是,数据上下文通常是为视图模型保留的,因此这可能不是一个好主意。在您的情况下,您只需要从可视树绑定到所需的源。服务的所有部分:)及时编辑为您赢得了10分,否则将受到危害!使用Xaml的按钮:)感谢您的回答,我刚刚尝试了它,但不幸的是它似乎没有帮助-设置将标签的内容设置为其(RelativeSource Self)属性标题,该标题不存在(或者我错了吗?)。和Caption=“{Binding Path=Caption,RelativeSource={RelativeSource Mode=Self},Mode=OneWay}”将usercontrol的Caption属性设置为其自己的属性Caption,使其无效(或者我错了吗?)。然而,我可能误解了一些事情……我已经更新了答案。如果用户控件位于主窗口上,则需要从可视树中查找属性。上述解决方案应该有效。谢谢。我已经在Window.xaml中将datacontext设置为Window-在。。。同样,在用户控件中,这取决于您正在做什么。但是,数据上下文通常是为视图模型保留的,因此这可能不是一个好主意。在你的情况下,你只想结合到酸