2011-08-13 129 views
2

在WPF中,我正在为我的TODO程序创建一个简单的自定义控件。它应该执行以下操作:WPF ListBox自定义控件问题

  • 显示为带有上方的添加和删除按钮的ListBox。
  • 添加和删除按钮应该添加和删除我的基类中的项目。
    • 我有这方面的工作
  • 在按F2,我想列表框中的项目更改到一个TextBox控件。

我的主要问题/问题是:

  • 在onkeydown事件,我得到的错误:此操作只适用于具有应用此模板元素。我该如何解决这个问题?这是我想要按F2的地方,并且能够使TextBox可见并且Label不可见。
  • 有没有更好的方法来做到这一点?如果我的控件是按钮和文本框的容器,我不应该从ListBox继承吗?我是否应该从Control继承,并将其设置为容器?

    • 如果是这样,我该如何实现它?我是否基本在样式中使用以下代码,并删除OnKeyDown之类的替代,而是为TextBox注册KeyDown事件?如果您有任何建议,我会在这篇文章后尝试一下,但请告诉我。

我有一些东西之前紧密的合作,在下面的代码,但现在我想这个从我的主窗口XAML到自定义控制代码移动,我希望能够按下按钮进行编辑:

<!-- In my MainWindow.XAML --> 
<TaskDashControls:ListBoxWithAddRemove x:Name="listBoxItems" Grid.Row="1" Grid.Column="3" Grid.RowSpan="3" 
     ItemsSource="{Binding}"> 
    <TaskDashControls:ListBoxWithAddRemove.ItemTemplate> 
     <DataTemplate> 
      <DockPanel> 
       <Button DockPanel.Dock="Left" Click="SelectItemClick">SELECT</Button> 
       <TextBlock x:Name="LabelDescription" Visibility="Visible" DockPanel.Dock="Left" Text="{Binding Description}" Height="25" Width="150" /> 
       <TextBox x:Name="EditableDescription" Visibility="Collapsed" DockPanel.Dock="Left" Text="{Binding Description}" Height="25" Width="150" /> 
       <Button DockPanel.Dock="Left" Click="EditTaskItemClick">EDIT</Button> 
      </DockPanel> 
     </DataTemplate> 
    </TaskDashControls:ListBoxWithAddRemove.ItemTemplate> 
</TaskDashControls:ListBoxWithAddRemove> 

我现在已经删除的DataTemplate,将其移动到自定义控制:

<!-- In my MainWindow.XAML --> 
<TaskDashControls:ListBoxWithAddRemove x:Name="listBoxItems" Grid.Row="1" Grid.Column="3" Grid.RowSpan="3" 
     ItemsSource="{Binding}"/> 

这里是Generic.XAML自定义控件:

<ResourceDictionary 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="clr-namespace:TaskDash.Controls"> 


<SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" /> 
<SolidColorBrush x:Key="SolidBorderBrush" Color="#888" /> 
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" /> 
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" /> 
<SolidColorBrush x:Key="DisabledBorderBrush" Color="#AAA" /> 


<Style TargetType="{x:Type TextBox}"> 
    <Setter Property="Margin" Value="2" /> 
</Style> 


<Style x:Key="{x:Type local:ListBoxWithAddRemove}" TargetType="{x:Type local:ListBoxWithAddRemove}"> 
    <Setter Property="Margin" Value="3" /> 
    <Setter Property="SnapsToDevicePixels" Value="True"/> 
    <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/> 
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/> 
    <Setter Property="MinWidth" Value="120"/> 
    <Setter Property="MinHeight" Value="20"/> 
    <Setter Property="AllowDrop" Value="true"/> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate> 
       <Grid> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="25" /> 
         <RowDefinition Height="*" /> 
        </Grid.RowDefinitions> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="*" /> 
         <ColumnDefinition Width="*" /> 
        </Grid.ColumnDefinitions> 

        <!--<Button Grid.Column="0" Grid.Row="0" x:Name="DeleteButton" 
            Click="DeleteControlClick">Delete</Button> 
        <Button Grid.Column="1" Grid.Row="0" x:Name="AddButton" 
            Click="AddControlClick">Add</Button>--> 
        <Button Grid.Column="0" Grid.Row="0" x:Name="DeleteButton">Delete</Button> 
        <Button Grid.Column="1" Grid.Row="0" x:Name="AddButton">Add</Button> 
        <Border 
           Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" 
            Name="Border" 
            Background="{StaticResource WindowBackgroundBrush}" 
            BorderBrush="{StaticResource SolidBorderBrush}" 
            BorderThickness="1" 
            CornerRadius="2"> 
         <ScrollViewer 
            Margin="0" 
            Focusable="false"> 
          <StackPanel Margin="0" IsItemsHost="True" /> 
         </ScrollViewer> 

         <!--<ListBox ItemTemplate="{TemplateBinding ItemTemplate}"> 
          <DataTemplate> 
           <DockPanel> 
            <TextBlock x:Name="LabelDescription" Visibility="Visible" DockPanel.Dock="Left" Text="{Binding Description}" Height="25" Width="150" /> 
            <TextBox x:Name="EditableDescription" DockPanel.Dock="Left" Text="{Binding Description}" Height="25" Width="150" /> 
           </DockPanel> 
          </DataTemplate> 
         </ListBox>--> 

        </Border> 
       </Grid> 
      </ControlTemplate> 

     </Setter.Value> 
    </Setter> 
</Style> 

这里是我的自定义控制类

using System; 
using System.Windows; 
using System.Windows.Controls; 

namespace TaskDash.Controls 
{ 
[TemplatePart(Name = "Text", Type = typeof(TextBox))] 
[TemplatePart(Name = "LabelText", Type = typeof(TextBlock))] 
public class TextBoxWithDescription : Control 
{ 
    static TextBoxWithDescription() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxWithDescription), new FrameworkPropertyMetadata(typeof(TextBoxWithDescription))); 
    } 

    public TextBoxWithDescription() 
    { 
     LabelText = String.Empty; 
     Text = String.Empty; 
    } 

    public static readonly DependencyProperty LabelTextProperty = 
     DependencyProperty.Register("LabelText", typeof(string), typeof(TextBoxWithDescription), 
     new PropertyMetadata(string.Empty, OnLabelTextPropertyChanged)); 
    private static void OnLabelTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 

    } 
    public string LabelText 
    { 
     get { return GetValue(LabelTextProperty).ToString(); ; } 
     set { SetValue(LabelTextProperty, value); } 
    } 

    // http://xamlcoder.com/cs/blogs/joe/archive/2007/12/13/building-custom-template-able-wpf-controls.aspx 
    public static readonly DependencyProperty TextProperty = 
     DependencyProperty.Register("Text", typeof(string), typeof(TextBoxWithDescription), 
     new UIPropertyMetadata(null, 
           new PropertyChangedCallback(OnTextChanged) 
          )); 
    private static void OnTextChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
    { 
     TextBoxWithDescription textBox = o as TextBoxWithDescription; 
     if (textBox != null) 
      textBox.OnTextChanged((String)e.OldValue, (String)e.NewValue); 
    } 
    protected virtual void OnTextChanged(String oldValue, String newValue) 
    { 
     // fire text changed event 
     this.Text = newValue; 
     this.RaiseEvent(new RoutedEventArgs(TextChangedEvent, this)); 
    } 
    public string Text 
    { 
     get { return GetValue(TextProperty).ToString(); } 
     set { SetValue(TextProperty, value); } 
    } 
    public static readonly RoutedEvent TextChangedEvent = 
     EventManager.RegisterRoutedEvent("TextChanged", 
           RoutingStrategy.Bubble, 
           typeof(RoutedEventHandler), 
           typeof(TextBoxWithDescription)); 
    public event RoutedEventHandler TextChanged 
    { 
     add { AddHandler(TextChangedEvent, value); } 
     remove { RemoveHandler(TextChangedEvent, value); } 
    } 



    public override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 

     //var textBlock = (TextBlock)this.Template.FindName("LabelText", this); 
     //if (textBlock != null) textBlock.Text = this.LabelText; 


     //var textBox = (TextBox)this.Template.FindName("Text", this); 
     //if (textBox != null) textBox.Text = this.Text; 
    } 
} 
} 

回答

1

我会为TODO创建一个具有属性的类:String Desc,Visibility txtBox,Visibility txtBlock。然后TaskDashControls的项目源是List TODO。在xaml中,您可以绑定visibilty属性。在TODO课程中,您可以控制一个可见时另一个不可见的情况。

+0

几乎可以工作,但是如果我按F2键,bools会切换,但Visibility属性不会更新以反映更改。 您是否看到任何问题? 'set {_isEditing = value; OnPropertyChanged( “IsEditing”); OnPropertyChanged( “IsDisplaying”); } ' – Shawn

+0

可见性不是布尔值。它是一个枚举(可见,折叠,隐藏)。但有一个系统转换器布尔可见性。 – Paparazzi