在WPF中创建自定义控件

时间:2015-09-30 06:32:11

标签: c# wpf custom-controls

定制控件的内容定义如下:

   db=  MySQLdb.connect("127.0.0.1","db_username","db_password","db_name")

<DockPanel>
<ListView x:Name="TabControlMenu" DockPanel.Dock="Top" ScrollViewer.VerticalScrollBarVisibility="Disabled"
          ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=Items}">
    <ListView.Resources>
        <Style BasedOn="{StaticResource ListViewStyle}" TargetType="{x:Type ListView}" />
        <Style BasedOn="{StaticResource ListViewItemStyle}" TargetType="{x:Type ListViewItem}" />
    </ListView.Resources>            
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"></StackPanel>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
</ListView>
<Border BorderBrush="Black" BorderThickness="1,0,0,0" DockPanel.Dock="Bottom">
    <ContentPresenter DataContext="{Binding SelectedItem}" Content="{Binding Body, ElementName=ThisControl}" />
</Border>

并像这样使用它:

public partial class MyTabControl : UserControl {

    #region static properties

    public static readonly DependencyProperty BodyProperty = DependencyProperty.Register(
        "Body",
        typeof(object),
        typeof(MyTabControl ),
        new UIPropertyMetadata(null));

    public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
        "Items",
        typeof(ObservableCollection<object>),
        typeof(MyTabControl),
        new UIPropertyMetadata(null));

    public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
        "SelectedItem",
        typeof(object),
        typeof(MyTabControl),
        new UIPropertyMetadata(null));

    #endregion

    #region public properties

    public object Body {
        get { return GetValue(BodyProperty); }
        set { SetValue(BodyProperty, value); }
    }

    public ObservableCollection<object> Items {
        get { return (ObservableCollection<object>)GetValue(ItemsProperty); }
        set { SetValue(ItemsProperty, value); }
    }

    public object SelectedItem {
        get { return GetValue(SelectedItemProperty); }
        set { SetValue(SelectedItemProperty, value); }
    }

    public ObservableCollection<ListViewItem> ListViewItems { get; set; }

    #endregion

    public MyTabControl() {
        InitializeComponent();

        ListViewItems = new ObservableCollection<ListViewItem>();
    }

}

如何设置<Controls:MyTabControl Margin="5,0,0,0" Items="{Binding Items}"> <Controls:MyTabControl.Body> <ContentControl Content=" WHAT BINDING GOES HERE???? "> <!--<ContentControl Content="{Binding}">--> <ContentControl.Resources> <DataTemplate DataType="{x:Type ViewModels:ProjectViewModel}"> <Partials:ProjectView DataContext="{Binding Path=.}" /> </DataTemplate> <DataTemplate DataType="{x:Type ViewModels:TestSuiteViewModel}"> <Partials:TestSuiteView DataContext="{Binding Path=.}" /> </DataTemplate> <DataTemplate DataType="{x:Type ViewModels:StepViewModel}"> <Partials:StepView DataContext="{Binding Path=.}" /> </DataTemplate> </ContentControl.Resources> </ContentControl> </Controls:MyTabControl.Body> </Controls:MyTabControl> ContentControl绑定,以便它指向Content内定义的内容?

可能有些人会问我为什么要首先创建自定义标签控件 - 答案是:因为我必须做一些不标准的事情 - 分组标签,着色,拖动等等......

编辑:

我的目标是让MyTabControl的行为像标准的WPF MyTabControl - 所以TabControlItems应绑定到某些集合和内容选项卡应该绑定到当前选择的任何内容。为了实现这一目标,我在我的控制代码后面绑定ItemsSourceListView集合,并尝试将Items&#39; s ContentPresenter绑定到任何位置当前选中(它也在后面的代码中设置)。问题是如果我在应用程序的某个地方使用DataContext,我就不知道如何绑定MyTabControl.Body属性,以便从我的自定义控件中获取它的数据。

1 个答案:

答案 0 :(得分:0)

如果我理解正确,您需要将UserControl设为DataContext。问题是,您希望UserControl中的控件将UserControl视为DataContext,但您需要UserControl本身才能看到其他Datacontext 。您可以通过设置根布局元素的DataContext来实现,我认为这是DockPanel。像这样:

<UserControl 
   ... 
   x:Name="ThisControl 
   ... >

   <DockPanel DataContext="{Binding ElementName=ThisControl}">

      ...
     </ListView>
     ...
   </DockPanel>
</UserControl>

http://www.codeproject.com/Articles/325911/A-Simple-Pattern-for-Creating-Re-useable-UserContr是对我想说的内容的正确解释。

编辑: 我认为你可能需要DataContext来获取ContentPresenter

<DockPanel DataContext="{Binding ElementName=ThisControl}">
...
  <ListView ItemsSource="{Binding Items}" ... />

  <Border ... >
    <ContentPresenter DataContext="{Binding SelectedItem}"  ... />
  </Border>

或者您使用RelativeSourceContentPresenter执行此操作,就像ItemsSourceListView<DockPanel> <ListView ... ItemsSource="{Binding RelativeSource= {RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=Items}"> ... </ListView> <Border ...> <ContentPresenter DataContext="{Binding RelativeSource= {RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.SelectedItem}" ... /> </Border> 一样:

MyTabControl

第二次编辑:

看起来你正试图在XAML级别设置<Controls:MyTabControl ... Body="{Binding TheBody}" Items="{Binding TheItems}"> SelectedItem="{Binding TheSelectedItem}" /> 的属性,但我认为你应该设置的是XAML绑定的DP。像这样? :

quoted_code = quote do: %{}
"%{}" = some_func(quoted_code)