1

I'm working on a UserControl (named DiagramControl) and have a problem. The UserControl's code is as follows:

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

I am binding the ZoomBox (which has a scrollviewer DP) to DesignerScrollViewer. The method I use now works fine since the ZoomBox and DesignerScrollViewer are in the same XAML file.

What I would like to do however is to remove the ZoomBox from the control and define it in the window that uses the control. so for example something like:

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

I tried this but it doesn't work. How can I perform the binding that I need?

UPDATE:

I figured out what I needed to do. I added a ScrollViewer DP to DiagramControl and had it update when the DesignerScrollViewer's Layout was updated. so the following went into my DiagramControl code behind:

        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;
    }

Now that the ScrollViewer DP had an update source i was able to bind to it from the window using the DiagramControl. Hope this helps someone in future.

4

1 回答 1

1

首先,您不应该将 UI 控件放入视图模型属性中(没有充分的理由 - 让视图模型保存所有信息并与之绑定)- 您的结构(视图 <-> 视图模型)也会得到“参与”并导致越来越多的黑客攻击 - 不碍事:) ...

如果我做对了,你在追求什么...

DesignerScrollViewer只是一个“子控件”,绑定标记扩展不知道它。

如果您想要类似的东西,请在上面制作一个 DesignerScrollViewerProperty并将UserControl其放入路径中(保留该ElementName部分)。那可能只是一个属性(您需要INotifyPropertyChanged并引发事件)。

或者有点不同,比如......

在你的窗口某处:

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

你的缩放框:

<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>

您的图表控件:

<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值进行绑定以来回循环等。

于 2013-03-22T01:01:34.807 回答