Wpf 如何使用列定义。是否正确添加?
我从第5章“WPF 4.5释放版”中复制了一个关于dock panel的示例。在本例中,dock设置在网格的右侧,因此在代码隐藏Wpf 如何使用列定义。是否正确添加?,wpf,xaml,Wpf,Xaml,我从第5章“WPF 4.5释放版”中复制了一个关于dock panel的示例。在本例中,dock设置在网格的右侧,因此在代码隐藏layer0.ColumnDefinitions.Add(column1CloneForLayer0)中时时,将在网格右侧创建内容为column1CloneForLayer0的列。 在我的项目中,我几乎做了同样的事情,但是当我调用函数来添加包含某些内容的列时,在右侧创建了一些空白。。这与预期不符。那么正确的做法是什么呢? 1.如何在网格左侧添加列 2.在本例中,列已创
layer0.ColumnDefinitions.Add(column1CloneForLayer0)中时调用代码>时,将在网格右侧创建内容为column1CloneForLayer0
的列。
在我的项目中,我几乎做了同样的事情,但是当我调用函数来添加包含某些内容的列时,在右侧创建了一些空白。。这与预期不符。那么正确的做法是什么呢?1.如何在网格左侧添加列 2.在本例中,列已创建,但为什么为空?也许我需要设置Z索引 更新 我在书中的原始示例中添加了一些类似的内容,得到了错误的结果。下面是源代码。我刚刚在左边添加了一个
leftToolBox
。
更新2
相关代码:在这种情况下,我只需在左侧添加一个带有按钮的stackpanel,然后单击调用DocakPane(3)
,而不是在左侧提供新列,而是在右侧创建列
public void DockPane(int paneNumber)
{
if (paneNumber == 1)
{
pane1Button.Visibility = Visibility.Collapsed;
pane1PinImage.Source = new BitmapImage(new Uri("pin.gif", UriKind.Relative));
// Add the cloned column to layer 0:
layer0.ColumnDefinitions.Add(column1CloneForLayer0);
// Add the cloned column to layer 1, but only if pane 2 is docked:
if (pane2Button.Visibility == Visibility.Collapsed) layer1.ColumnDefinitions.Add(column2CloneForLayer1);
}
else if (paneNumber == 2)
{
pane2Button.Visibility = Visibility.Collapsed;
pane2PinImage.Source = new BitmapImage(new Uri("pin.gif", UriKind.Relative));
// Add the cloned column to layer 0:
layer0.ColumnDefinitions.Add(column2CloneForLayer0);
// Add the cloned column to layer 1, but only if pane 1 is docked:
if (pane1Button.Visibility == Visibility.Collapsed) layer1.ColumnDefinitions.Add(column2CloneForLayer1);
}
else
{
leftpane1Button.Visibility = Visibility.Collapsed;
pane3PinImage.Source = new BitmapImage(new Uri("pin.gif", UriKind.Relative));
layer0.ColumnDefinitions.Add(testcol);
}
}
基于提供的示例项目,下面是使用MVVM对其进行的重写,与硬编码相关的大部分问题都将消失。它不是纯粹的MVVM,但它主要是MVVM 首先定义ViewModels 表示停靠窗格的类
class DockablePaneVM : ViewModelBase
{
public DockablePaneVM(DockHostVM host)
{
Host = host;
}
private string _title;
public string Title
{
get { return _title; }
set
{
_title = value;
RaisePropertyChanged("Title");
}
}
private bool _isPinned;
public bool IsPinned
{
get { return _isPinned; }
set
{
_isPinned = value;
Host.PinModeChanged(this);
RaisePropertyChanged("IsPinned");
}
}
private object _content;
public object Content
{
get { return _content; }
set
{
_content = value;
RaisePropertyChanged("Content");
}
}
public DockHostVM Host { get; private set; }
public Dock Dock { get; set; }
}
作为dockpanes的主机,我使用collectionview简化了位置
class DockHostVM : ViewModelBase
{
public DockHostVM()
{
Panes = new ObservableCollection<DockablePaneVM>();
LeftPanes = new CollectionViewSource() { Source = Panes }.View;
RightPanes = new CollectionViewSource() { Source = Panes }.View;
FlotingLeftPanes = new CollectionViewSource() { Source = Panes }.View;
FlotingRightPanes = new CollectionViewSource() { Source = Panes }.View;
LeftPanes.Filter = o => Filter(o, Dock.Left, true);
RightPanes.Filter = o => Filter(o, Dock.Right, true);
FlotingLeftPanes.Filter = o => Filter(o, Dock.Left, false);
FlotingRightPanes.Filter = o => Filter(o, Dock.Right, false);
}
private bool Filter(object obj, Dock dock, bool isPinned)
{
DockablePaneVM vm = obj as DockablePaneVM;
return vm.Dock == dock && vm.IsPinned == isPinned;
}
public ObservableCollection<DockablePaneVM> Panes { get; set; }
public ICollectionView LeftPanes { get; set; }
public ICollectionView RightPanes { get; set; }
public ICollectionView FlotingLeftPanes { get; set; }
public ICollectionView FlotingRightPanes { get; set; }
private object _content;
public object Content
{
get { return _content; }
set { _content = value; }
}
public void PinModeChanged(DockablePaneVM paneVM)
{
LeftPanes.Refresh();
RightPanes.Refresh();
FlotingLeftPanes.Refresh();
FlotingRightPanes.Refresh();
}
//sample generator
public static DockHostVM GetSample()
{
DockHostVM vm = new DockHostVM();
vm.Panes.Add(new DockablePaneVM(vm) { Title = "Left Toolbox", Content = new ToolBoxVM() });
vm.Panes.Add(new DockablePaneVM(vm) { Title = "Solution Explorer", Content = new SolutionExplorerVM(), Dock = Dock.Right });
vm.Panes.Add(new DockablePaneVM(vm) { Title = "Toolbox", Content = new ToolBoxVM(), Dock = Dock.Right });
return vm;
}
}
类DockHostVM:ViewModelBase
{
公共DockHostVM()
{
窗格=新的可观察集合();
LeftPanes=new CollectionViewSource(){Source=Panes}.View;
RightPanes=new CollectionViewSource(){Source=Panes}.View;
FlotingLeftPanes=new CollectionViewSource(){Source=Panes}.View;
FlotingRightPanes=new CollectionViewSource(){Source=Panes}.View;
LeftPanes.Filter=o=>Filter(o,Dock.Left,true);
RightPanes.Filter=o=>Filter(o,Dock.Right,true);
FlotingLeftPanes.Filter=o=>Filter(o,Dock.Left,false);
FlotingRightPanes.Filter=o=>Filter(o,Dock.Right,false);
}
专用布尔过滤器(对象对象对象、Dock Dock、布尔Ispined)
{
DockablePaneVM vm=obj作为DockablePaneVM;
返回vm.Dock==Dock&&vm.IsPinned==IsPinned;
}
公共可观察集合窗格{get;set;}
公共ICollectionView左窗格{get;set;}
公共ICollectionView右窗格{get;set;}
公共ICollectionView浮动左窗格{get;set;}
public ICollectionView FlotingRightPanes{get;set;}
私有对象内容;
公共对象内容
{
获取{return\u content;}
设置{u content=value;}
}
公共无效PinModeChanged(DockablePaneVM paneVM)
{
LeftPanes.Refresh();
右窗格。刷新();
FlotingLeftPanes.Refresh();
FlotingRightPanes.Refresh();
}
//样品发生器
公共静态DockHostVM GetSample()
{
DockHostVM=新的DockHostVM();
添加(新的DockablePaneVM(vm){Title=“Left Toolbox”,Content=new ToolBoxVM()});
添加(new-DockablePaneVM(vm){Title=“解决方案浏览器”,Content=new-SolutionExplorerVM(),Dock=Dock.Right});
添加(新的DockablePaneVM(vm){Title=“Toolbox”,Content=newtoolboxvm(),Dock=Dock.Right});
返回虚拟机;
}
}
然后是样式,以提供类的视图
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:VisualStudioLikePanes">
<DataTemplate DataType="{x:Type l:DockablePaneVM}">
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<TextBlock Padding="8,4"
Text="{Binding Title}"
TextTrimming="CharacterEllipsis"
Background="{DynamicResource {x:Static SystemColors.ActiveCaptionBrushKey}}"
Foreground="{DynamicResource {x:Static SystemColors.ActiveCaptionTextBrushKey}}" />
<ToggleButton IsChecked="{Binding IsPinned}"
Grid.Column="1">
<Image Name="pinImage"
Source="pinHorizontal.gif" />
</ToggleButton>
<ContentControl Content="{Binding Content}"
Grid.Row="1"
Grid.ColumnSpan="2" />
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsPinned}"
Value="True">
<Setter Property="Source"
TargetName="pinImage"
Value="pin.gif" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<Style TargetType="TabItem">
<Setter Property="Header"
Value="{Binding Title}" />
</Style>
<Style TargetType="TabItem"
x:Key="FloterItem"
BasedOn="{StaticResource {x:Type TabItem}}">
<Setter Property="LayoutTransform">
<Setter.Value>
<RotateTransform Angle="90" />
</Setter.Value>
</Setter>
</Style>
<Style TargetType="TabControl">
<Setter Property="l:TabControlHelper.IsLastItemSelected"
Value="True" />
<Style.Triggers>
<Trigger Property="HasItems"
Value="false">
<Setter Property="Visibility"
Value="Collapsed" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="TabControl"
x:Key="AutoResizePane"
BasedOn="{StaticResource {x:Type TabControl}}">
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="false">
<Setter Property="Width"
Value="23" />
</Trigger>
</Style.Triggers>
</Style>
<DataTemplate DataType="{x:Type l:ToolBoxVM}">
<ListBox Padding="10"
Grid.Row="1">
<ListBoxItem>Button</ListBoxItem>
<ListBoxItem>CheckBox</ListBoxItem>
<ListBoxItem>ComboBox</ListBoxItem>
<ListBoxItem>Label</ListBoxItem>
<ListBoxItem>ListBox</ListBoxItem>
</ListBox>
</DataTemplate>
<DataTemplate DataType="{x:Type l:SolutionExplorerVM}">
<TreeView Grid.Row="2">
<TreeViewItem Header="My Solution" IsExpanded="True">
<TreeViewItem Header="Project #1" />
<TreeViewItem Header="Project #2" />
<TreeViewItem Header="Project #3" />
</TreeViewItem>
</TreeView>
</DataTemplate>
</ResourceDictionary>
按钮
复选框
组合框
标签
列表框
我还创建了一些虚拟类来表示工具箱和解决方案资源管理器
这也是一个帮助类,用于提高我用来托管dockpanes的选项卡控件的可用性
class TabControlHelper
{
public static bool GetIsLastItemSelected(DependencyObject obj)
{
return (bool)obj.GetValue(IsLastItemSelectedProperty);
}
public static void SetIsLastItemSelected(DependencyObject obj, bool value)
{
obj.SetValue(IsLastItemSelectedProperty, value);
}
// Using a DependencyProperty as the backing store for IsLastItemSelected. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsLastItemSelectedProperty =
DependencyProperty.RegisterAttached("IsLastItemSelected", typeof(bool), typeof(TabControlHelper), new PropertyMetadata(false, OnIsLastItemSelected));
private static void OnIsLastItemSelected(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TabControl tc = d as TabControl;
tc.Items.CurrentChanged += (ss, ee) =>
{
if (tc.SelectedIndex < 0 && tc.Items.Count > 0)
tc.SelectedIndex = 0;
};
}
}
类TabControlHelper
{
公共静态bool GetIsLastItemSelected(DependencyObject obj)
{
返回(bool)对象GetValue(IsLastItemSelectedProperty);
}
公共静态void SetIsLastItemSelected(DependencyObject对象,布尔值)
{
obj.SetValue(IsLastItemSelectedProperty,值);
}
//使用DependencyProperty作为IsLastItemSelected的后备存储。这将启用动画、样式、绑定等。。。
public static readonly dependencProperty IsLastItemSelectedProperty=
DependencyProperty.RegisterAttached(“IsLastItemSelected”、typeof(bool)、typeof(TabControlHelper)、new PropertyMetadata(false、OnIsLastItemSelected));
已选择专用静态void onislatimes(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
TabControl tc=d作为TabControl;
tc.Items.CurrentChanged+=(ss,ee)=>
{
如果(tc.SelectedIndex<0&&tc.Items.Count>0)
tc.SelectedIndex=0;
};
}
}
这将使项目随时处于选中状态,在此项目中,固定/取消固定停靠窗格时将使用该项目
现在是主窗口,请注意,我已经将停靠窗格限定为4个选项卡控件,左、右、左浮动和右浮动
<Window x:Class="VisualStudioLikePanes.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="500"
Width="800"
WindowStartupLocation="CenterScreen"
xmlns:l="clr-namespace:VisualStudioLikePanes">
<Window.DataContext>
<ObjectDataProvider MethodName="GetSample"
ObjectType="{x:Type l:DockHostVM}" />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Menu>
<MenuItem Header="FILE" />
...
<MenuItem Header="HELP" />
</Menu>
<DockPanel LastChildFill="True"
Grid.Row="1">
<Border Width="23"
DockPanel.Dock="Left"
Visibility="{Binding Visibility, ElementName=LeftFloter}" />
<Border Width="23"
DockPanel.Dock="Right"
Visibility="{Binding Visibility, ElementName=RightFloter}" />
<TabControl ItemsSource="{Binding LeftPanes}"
DockPanel.Dock="Left" />
<TabControl ItemsSource="{Binding RightPanes}"
DockPanel.Dock="Right" />
<Grid Name="layer0">
... page content
</Grid>
</DockPanel>
<TabControl ItemsSource="{Binding FlotingLeftPanes}"
Grid.Row="1"
HorizontalAlignment="Left"
TabStripPlacement="Left"
Style="{StaticResource AutoResizePane}"
ItemContainerStyle="{StaticResource FloterItem}"
x:Name="LeftFloter" />
<TabControl ItemsSource="{Binding FlotingRightPanes}"
Grid.Row="1"
HorizontalAlignment="Right"
TabStripPlacement="Right"
Style="{StaticResource AutoResizePane}"
ItemContainerStyle="{StaticResource FloterItem}"
x:Name="RightFloter" />
</Grid>
</Window>
...