绑定到兄弟的子元素

时间:2013-03-21 22:54:22

标签: wpf binding wpf-controls siblings

我正在使用UserControl(名为DiagramControl)并遇到问题。 UserControl的代码如下:

<UserControl>
   <Border>
      <Grid>
         <ScrollViewer x:Name="DesignerScrollViewer" ... />               
         ...
         <s:ZoomBox x:Name="zoomBox"
                   ScrollViewer="{Binding ElementName=DesignerScrollViewer}"/>
      </Grid>
   </Border>
</UserControl>

我将ZoomBox(具有scrollviewer DP)绑定到DesignerScrollViewer。我现在使用的方法工作正常,因为ZoomBox和DesignerScrollViewer在同一个XAML文件中。

然而,我想要从控件中删除ZoomBox并在使用该控件的窗口中定义它。例如:

<Grid>
   <s:DiagramControl x:Name="DC" ... />
   ...
   <s:ZoomBox ScrollViewer={Binding ElementName=DC,Path=DesignerScrollViewer}/>
</Grid>

我尝试了这个,但它不起作用。如何执行我需要的绑定?

更新

我想出了我需要做的事情。我将一个ScrollViewer DP添加到DiagramControl,并在更新DesignerScrollViewer的布局时更新它。所以以下内容进入了我的DiagramControl代码:

        public static readonly DependencyProperty ScrollViewerProperty =
            DependencyProperty.Register("ScrollViewer", typeof(ScrollViewer), typeof(DiagramControl), new UIPropertyMetadata(null, ScrollViewer_PropertyChanged));

        public ScrollViewer ScrollViewer
        {
            get { return (ScrollViewer)GetValue(ScrollViewerProperty); }
            set { SetValue(ScrollViewerProperty, value); }
        }

        private static void ScrollViewer_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {                
        }

        private void DesignerScrollViewer_LayoutUpdated(object sender, EventArgs e)
    {
        ScrollViewer = DesignerScrollViewer;
    }

现在ScrollViewer DP有一个更新源,我可以使用DiagramControl从窗口绑定它。希望这有助于将来。

1 个答案:

答案 0 :(得分:1)

首先,你不应该将UI控件放入视图模型属性中(没有充分的理由 - 让视图模型保存所有信息并绑定到它) - 你的结构(视图&lt; - &gt;视图-model)变得过于“参与”并导致越来越多的黑客攻击 - 这就是... ...

如果我说得对,那你正在追求......

您的DesignerScrollViewer仅仅是一个'子控件',绑定标记扩展程序并不知道它。

  

如果你想要这样的话   DesignerScrollViewerProperty上的UserControl并将其放入   路径(保留ElementName部分)。那可能只是一个财产   (你需要INotifyPropertyChanged并举起活动。)

或者有点不同,像是......

在你的窗口某处:

<my:ZoomBox DataContext="{Binding ElementName=diagramControl, Path=.}"></my:ZoomBox>
<my:DiagramControl x:Name="diagramControl"></my:DiagramControl>

你的ZoomBox:

<UserControl x:Class="YourApp.ZoomBox" ...="">
    <StackPanel>
        <Button x:Name="GoUp" Command="{Binding UpCommand}" Content="Go Up" IsDefault="False" />
        <Button x:Name="GoDown" Command="{Binding DownCommand}" Content="Go Down" IsDefault="False" />
    </StackPanel>
</UserControl>

你的DiagramControl:

<UserControl x:Class="YourApp.DiagramControl" ...="">
    <Grid>
        <ScrollViewer x:Name="_scrollViewer" >
            ...
        </ScrollViewer>
    </Grid>
</UserControl>

...和图表代码背后......

public partial class DiagramControl : UserControl, INotifyPropertyChanged
{
    RelayCommand _upCommand;
    RelayCommand _downCommand;
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName) { this.PropertyChanged.Raise(this, new PropertyChangedEventArgs(propertyName)); }

    public DiagramControl()
    {
        InitializeComponent();
    }

    public RelayCommand UpCommand 
    { 
        get 
        {
            return _upCommand ?? (_upCommand = new RelayCommand(
                param =>
                {
                    _scrollViewer.LineUp();
                },
                param => true)); 
        } 
    }

    public RelayCommand DownCommand
    {
        get
        {
            return _downCommand ?? (_downCommand = new RelayCommand(
                param =>
                {
                    _scrollViewer.LineDown();
                },
                param => true));
        }
    }
}

...您可以绑定到您的DP(DataContext)。并放置你想要的任何动作(例如放大/缩小)而不是上/下。

这仍然是不正确的,为了使它正常 - 你应该将你的图表和缩放框绑定到相同的视图模型(直接跳过绑定到用户控件 - 但是通过视图模型间接地“通信”) - 但是这会使一些事情变得复杂,因为你需要一些事件来处理命令,并使值TwoWay来使值来回传播等。