2011-11-28 82 views
1

我做了一个模板,看起来像这样:动态模板WPF

<ControlTemplate x:Key="onoffValue" TargetType="{x:Type Control}"> 
      <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Height="20" Margin="0,5,0,0"> 
       <RadioButton Content="On" Height="20" Name="On_radiobutton" /> 
       <RadioButton Content="Off" Height="20" Name="Off_radiobutton" Margin="20,0,0,0" /> 
      </StackPanel> 
    <ControlTemplate.Triggers> 
       <DataTrigger Binding="{Binding Path=BootSector}" Value="true"> 
        <Setter TargetName="On_radiobutton" Property="IsChecked" Value="true"/> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding Path=BootSector}" Value="false"> 
        <Setter TargetName="Off_radiobutton" Property="IsChecked" Value="true"/> 
       </DataTrigger> 
    </ControlTemplate.Triggers> 
</ControlTemplate> 

现在,它被绑定到物业启动扇区(布尔)OFA“配置”对象。

我用这个模板在我的窗口,有一个配置对象作为这样的数据上下文:

<Control Template="{StaticResource onoffValue}"> 

</Control> 

它的伟大工程,但我想走得更远。

我想知道我怎么可以在不同的属性传递给我的模板动态绑定(动态更改模板绑定属性) 即我tryed像

<Control Template="{StaticResource onoffValue}" xmlns:test="{Binding Path=BootSector}"/> 

,并将其绑定在模板“测试”但它不起作用

这可能吗?我怎样才能做到这一点 ?我认为我不是太远,但还没有!

预先感谢您

编辑:关于梅德答案:
有使用中的错误。当我这样做时:

<StackPanel local:ToggleControl.IsOn="{Binding BootSector, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
       Grid.Row="0" Grid.Column="1" 
     Orientation="Horizontal" HorizontalAlignment="Center" Margin="5"> 
          <RadioButton Content="On" local:ToggleControl.Role="On" Height="20" Margin="5" /> 
          <RadioButton Content="Off" local:ToggleControl.Role="Off" Height="20" Margin="5" /> 
         </StackPanel> 

默认情况下BootSector为false。当我点击on按钮(true)时,它将bootSector设置为true,然后立即为false。行为应该是它保持为真,直到它未被选中?这与这里相关的问题有关吗? http://geekswithblogs.net/claraoscura/archive/2008/10/17/125901.aspx

+0

当用户点击单选按钮您目前的范本不改变“引导扇区”。这是期望的行为? – Jens

+0

它仍然是一个正在进行的工作,但我也希望这样做,如果你有任何意见,这将是伟大的太 – djfoxmccloud

+0

@djfoxmccloud你打算如何使用'模板模板'?说,你有它 - 你将如何利用它,你可以在这里发布样本? – 2011-11-28 11:59:29

回答

1

这里的想法是 - 通用行为从不复杂,通常不值得创建自定义控件。我承认,暗示可能会有所不同,但方法将保持不变。将XAML用于可以更改和编码将保持不变的内容的部分是有意义的。

UPDATE 1-使用自定义控件时,它变得更加简单。您不再需要附加属性 - 因为您可以在自定义控件中获得专用空间,并且可以使用x:Name和GetTemplateChild(..)创建对单个RadioButton的引用。

Code: 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.ComponentModel; 

namespace RadioButtons 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      this.Loaded += (o, e) => 
      { 
       this.DataContext = new TwoBoolean() 
       { 
        PropertyA = false, 
        PropertyB = true 
       }; 
      }; 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      MessageBox.Show(((TwoBoolean)this.DataContext).ToString()); 
     } 
    } 

    public enum RadioButtonRole 
    { 
     On, 
     Off 
    } 


    public class ToggleControl : DependencyObject 
    { 
     public static readonly DependencyProperty IsOnProperty = 
      DependencyProperty.RegisterAttached("IsOn", 
      typeof(bool?), 
      typeof(ToggleControl), 
      new PropertyMetadata(null, 
       new PropertyChangedCallback((o, e) => 
       { 
        ToggleControl.OnIsOnChanged((Panel)o, (bool)e.NewValue); 
       }))); 


     public static readonly DependencyProperty RoleProperty = 
      DependencyProperty.RegisterAttached("Role", 
      typeof(RadioButtonRole?), 
      typeof(ToggleControl), 
      new PropertyMetadata(null, 
       new PropertyChangedCallback((o, e) => 
       { 

       }))); 

     private static readonly DependencyProperty IsSetUpProperty = 
      DependencyProperty.RegisterAttached("IsSetUp", 
      typeof(bool), 
      typeof(ToggleControl), 
      new PropertyMetadata(false)); 

     private static void OnIsOnChanged(Panel panel, bool e) 
     { 
      if (!ToggleControl.IsSetup(panel)) 
      { 
       ToggleControl.Setup(panel); 
      } 

      RadioButtonRole role; 

      if (e) 
      { 
       role = RadioButtonRole.On; 
      } 
      else 
      { 
       role = RadioButtonRole.Off; 
      } 

      ToggleControl.GetRadioButtonByRole(role, panel).IsChecked = true; 
     } 

     private static void Setup(Panel panel) 
     { 
      // get buttons 
      foreach (RadioButton radioButton in 
       new RadioButtonRole[2] 
       { 
        RadioButtonRole.On, 
        RadioButtonRole.Off 
       }.Select(t => 
        ToggleControl.GetRadioButtonByRole(t, panel))) 
      { 
       radioButton.Checked += (o2, e2) => 
       { 
        RadioButton checkedRadioButton = (RadioButton)o2; 

        panel.SetValue(ToggleControl.IsOnProperty, 
         ToggleControl.GetRadioButtonRole(checkedRadioButton) == RadioButtonRole.On); 
       }; 
      } 

      panel.SetValue(ToggleControl.IsSetUpProperty, true); 
     } 

     private static bool IsSetup(Panel o) 
     { 
      return (bool)o.GetValue(ToggleControl.IsSetUpProperty); 
     } 

     private static RadioButton GetRadioButtonByRole(RadioButtonRole role, 
      Panel container) 
     { 
      return container.Children.OfType<RadioButton>().First(t => 
       (RadioButtonRole)t.GetValue(ToggleControl.RoleProperty) == role); 
     } 

     private static RadioButtonRole GetRadioButtonRole(RadioButton radioButton) 
     { 
      return (RadioButtonRole)radioButton.GetValue(ToggleControl.RoleProperty); 
     } 

     public static void SetIsOn(DependencyObject o, bool? e) 
     { 
      o.SetValue(ToggleControl.IsOnProperty, e); 
     } 

     public static bool? GetIsOn(DependencyObject e) 
     { 
      return (bool?)e.GetValue(ToggleControl.IsOnProperty); 
     } 

     public static void SetRole(DependencyObject o, RadioButtonRole? e) 
     { 
      o.SetValue(ToggleControl.RoleProperty, e); 
     } 

     public static RadioButtonRole? GetRole(DependencyObject e) 
     { 
      return (RadioButtonRole?)e.GetValue(ToggleControl.RoleProperty); 
     } 
    } 

    public class TwoBoolean: INotifyPropertyChanged 
    { 
     private bool propertyA, propertyB; 

     public bool PropertyA 
     { 
      get 
      { 
       return this.propertyA; 
      } 
      set 
      { 
       this.propertyA = value; 

       this.OnPropertyChanged("PropertyA"); 
      } 
     } 

     public bool PropertyB 
     { 
      get 
      { 
       return this.propertyB; 
      } 
      set 
      { 
       this.propertyB = value; 

       this.OnPropertyChanged("PropertyB"); 
      } 
     } 

     private void OnPropertyChanged(string propertyName) 
     { 
      if (this.PropertyChanged != null) 
      { 
       this.PropertyChanged(this, 
        new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     public override string ToString() 
     { 
      return string.Format("PropertyA:{0}, PropertyB:{1}", this.PropertyA, this.PropertyB); 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
    } 

} 

标记:

<Window x:Class="RadioButtons.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:RadioButtons" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition Height="Auto"/> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto" /> 
      <ColumnDefinition Width="Auto" /> 
     </Grid.ColumnDefinitions> 
     <TextBlock Grid.Row="0" Grid.Column="0" Margin="5" VerticalAlignment="Center">PropertyA</TextBlock> 
     <StackPanel local:ToggleControl.IsOn="{Binding PropertyA, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
        Grid.Row="0" Grid.Column="1" 
      Orientation="Horizontal" HorizontalAlignment="Center" Margin="5"> 
      <RadioButton Content="On" local:ToggleControl.Role="On" Height="20" Margin="5" /> 
      <RadioButton Content="Off" local:ToggleControl.Role="Off" Height="20" Margin="5" /> 
     </StackPanel> 

     <TextBlock Grid.Row="1" Grid.Column="0" Margin="5" VerticalAlignment="Center">PropertyB</TextBlock> 
     <StackPanel local:ToggleControl.IsOn="{Binding PropertyB, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
        Grid.Row="1" Grid.Column="1" 
      Orientation="Horizontal" HorizontalAlignment="Center" Margin="5"> 
      <RadioButton Content="On" local:ToggleControl.Role="On" Height="20" Margin="5" /> 
      <RadioButton Content="Off" local:ToggleControl.Role="Off" Height="20" Margin="5" /> 
     </StackPanel> 
     <Button Click="Button_Click" Grid.Row="3" Grid.ColumnSpan="2">Save</Button> 
    </Grid> 
</Window> 
+0

看到我的编辑与适当的代码 – djfoxmccloud

0

你不应该使用xmlns传递一个参数,而使用Tag或模板一个ContentControl,那么你可以将Content绑定到你的财产(其设置为TwoWay),并使用TemplateBindingContent在模板中。

+0

你有没有关于如何使用标签的例子? – djfoxmccloud

+0

@djoxmccloud:与使用Content相同的方式,你将它绑定到你的属性,并在模板中绑定到标签。 –

+0

所以我所做的是:并在模板中使用{Binding Tag,Mode = TwoWay}。但这不起作用 – djfoxmccloud