惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
博客园_首页
Google DeepMind News
Google DeepMind News
博客园 - Franky
The GitHub Blog
The GitHub Blog
GbyAI
GbyAI
有赞技术团队
有赞技术团队
Microsoft Azure Blog
Microsoft Azure Blog
G
Google Developers Blog
Recent Announcements
Recent Announcements
A
About on SuperTechFans
博客园 - 【当耐特】
博客园 - 三生石上(FineUI控件)
酷 壳 – CoolShell
酷 壳 – CoolShell
美团技术团队
罗磊的独立博客
IT之家
IT之家
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
Jina AI
Jina AI
腾讯CDC
P
Proofpoint News Feed
Hugging Face - Blog
Hugging Face - Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

博客园 - Sheva

Two Xaml Tricks - Sheva I See Cool Stuff Today DataTemplate Is A Bit Naughtier To Play With XmlnsDefinitionAttribute Is Pretty Nifty Application.DoEvents In WPF 征召译者 C# Trivia Test CreateParams Is Pretty Cool! SingleLinkedList Implementation Data Binding In WPF C# Application Markup Language Regex 101 Exercise I10 - Extract repeating hex blocks from a string AvalonPaint: Features Added Regex 101 Exercise I9 - Count the number of matches Crossbow: Hosting WPF Controls In Winforms Application Crossbow? WTF? The Architecture Of Avalon Drop Shadow Effect In WPF XamlReader.Load(): Build Up Your Own XamlPad
In-Place Editing In WPF
Sheva · 2006-04-27 · via 博客园 - Sheva

    Several days ago, Dflying Chen just shown us how to implement in-place editing functionality using ASP.NET Atlas framework, and the custom control he writes called InPlaceEditingInput is pretty cool indeed. In this post, I will show you how to achieve the same thing in WPF, and also demonstrate how the WPF makes our lives as programming hobbyists much easier:)
    WPF introduces a new concept called Control template, which means that you can replace the visual tree of any WPF element by defining a new ControlTemplate for the targeting element, and this capability makes writing a custom In-Place Editing WPF control much easier. the following code lists the ControlTemplate I define for the custom textbox control called InfoTextBox:

<Style TargetType="{x:Type itb:InfoTextBox}">
      
<Setter Property="FontSize" Value="20"/>
      
<Setter Property="Margin" Value="5"/>
      
<Setter Property="BorderBrush" Value="Black"/>
      
<Setter Property="BorderThickness" Value="1"/>
      
<Setter Property="Template">
        
<Setter.Value>
          
<ControlTemplate TargetType="{x:Type itb:InfoTextBox}">
            
              
<Grid Margin="0">
                
<Border Name="background"
                                Background
="{TemplateBinding Background}"
                                BorderBrush
="{TemplateBinding BorderBrush}"
                                BorderThickness
="{TemplateBinding BorderThickness}">
                
<Decorator x:Name="PART_ContentHost" VerticalAlignment="Top" Margin="0"/>
                
</Border>
                
<Label Content="{TemplateBinding TextBoxInfo}" 
                            x:Name
="Message"
                                        Foreground
="Gray" 
                                        Opacity
="0.9" 
                            FontSize
="{TemplateBinding FontSize}"
                            FontStyle
="Italic" 
                            HorizontalAlignment
="Left" 
                            VerticalAlignment
="Top"
                                        Margin
="0"/>
              
</Grid>
            
            
<ControlTemplate.Triggers><MultiTrigger>
                
<MultiTrigger.Conditions>
                  
<Condition Property="HasText" Value="False"/>
                  
<Condition Property="IsFocused" Value="True"/>
                
</MultiTrigger.Conditions>
                
<MultiTrigger.EnterActions>
                  
<BeginStoryboard Storyboard="{StaticResource enterGotFocus}"/>
                
</MultiTrigger.EnterActions>
                
<MultiTrigger.ExitActions>
                  
<BeginStoryboard Storyboard="{StaticResource exitGotFocus}"/>
                
</MultiTrigger.ExitActions>
              
</MultiTrigger>
              
              
<MultiTrigger>
                
<MultiTrigger.Conditions>
                  
<Condition Property="HasText" Value="False"/>
                  
<Condition Property="IsFocused" Value="False"/>
                
</MultiTrigger.Conditions>
                
<Setter TargetName="background" Property="Visibility" Value="Hidden"/>
              
</MultiTrigger><Trigger Property="HasText" Value="True">
                
<Setter TargetName="Message" Property="Visibility"  Value="Hidden"/>
              
</Trigger><Trigger Property="IsEnabled"
                                     Value
="false">
                
<Setter TargetName="background"
                                        Property
="Background"
                                        Value
="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                
<Setter Property="Foreground"
                                        Value
="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
              
</Trigger>
              
              
<Trigger Property="Width"
                                     Value
="Auto">
                
<Setter Property="MinWidth"
                                        Value
="100"/>
              
</Trigger><Trigger Property="Height"
                                     Value
="Auto">
                
<Setter Property="MinHeight"
                                        Value
="20"/>
              
</Trigger>
            
</ControlTemplate.Triggers>
          
</ControlTemplate>
        
</Setter.Value>
      
</Setter>
    
</Style>

   
    The above XAML markup is really worth a detailed explanation, WPF actually supports styling, so what's styling? well, you can think of WPF styling as the CSS for XHTML elments, with styling, you can easily change the look and feel of the WPF controls by grouping the style properties of a speficied control in a common location(usually in the ResourceDictionary collection). Another thing you might note is that I define a lot of triggers inside the style element, so what's triggers? a trigger represents a specific condition for a property value, when a trigger condition is met, it wil cause the associated setter XAML statement to change a control property's value, in the above XAML markup for instance, when the "HasText" property is set to true, it will change the "Message" Label element's Visibility property to "Hidden".
    As I mentioned earlier in this post, InfoTextBox is a custom control which is derived from System.Windows.Controls.TextBox, the actual implementation of this custom control is nothing more than adding two additional dependency properties for the base TextBox control, one is TextBoxInfoProperty, and the other is HasTextProperty as the following code demonstrates:

InfoTextBox Implementation


    After all those plumbing work completes, we can use the tailer-made control anywhere as we would like:

<GroupBox Header="Comment Form" FontSize="20" Margin="10" BorderBrush="LightBlue" BorderThickness="1" Padding="10">
      
<Grid Margin="0">
        
<Grid.RowDefinitions>
          
<RowDefinition/>
          
<RowDefinition/>
          
<RowDefinition/>
          
<RowDefinition/>
        
</Grid.RowDefinitions><Grid.ColumnDefinitions>
          
<ColumnDefinition Width="Auto"/>
        
</Grid.ColumnDefinitions>
        
<itb:InfoTextBox TextBoxInfo="Put Your Name Here" TextWrapping="NoWrap"  Grid.Row="0" Grid.Column="0"/>
        
<itb:InfoTextBox TextBoxInfo="Put Your Email Address Here" TextWrapping="NoWrap"  Grid.Row="1" Grid.Column="0"/>
        
<itb:InfoTextBox TextBoxInfo="Put Your Comment Here" TextWrapping="NoWrap" Grid.Row="2" Grid.Column="0"/>
        
<Button Content="Submit" Grid.Row="3" Grid.Column="0" Width="100" Height="30" HorizontalAlignment="Left"/>
      
</Grid>
    
</GroupBox>


    Here is the screenshot of my functionally complete in-place editing UI:

For complete source code, please check here.