none
How to implement auto wrap use trigger in notepad application RRS feed

  • 问题

  • I want to implement auto wrap use trigger , like notepad.

    <MenuItem Header="Format(_F)">
      <MenuItem Name="miAutoWrap" Header="Auto Wrap" IsChecked="True">
        <Style TargetType="{x:Type MenuItem}">
          <Style.Triggers>
            <Trigger Property="IsChecked" Value="True">
              <Setter TargetName="txtContent" Property="TextWrapping" Value="Wrap" />
            </Trigger>
          </Style.Triggers>
        </Style>
      </MenuItem>
    </MenuItem>
    

    but it can't use TargetName property in "Setter" tag.
    How to implement this function?


    Sonny.Lin
    2011年4月27日 2:34

答案

  • TargetName 只允许在ControlTemplate中的触发器用来指定某个模板元素的属性值,不能用于Style中的触发器。

    所以你的这个需求,可以反过来设计,如果有一个中间属性,同时邦定到了这个菜单项上和TextBox的Wrap属性上,就可以实现了:

    XAML:

    <Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication2"
        Title="MainWindow" Height="350" Width="525">
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Menu>
          <MenuItem Header="Format(_F)">
            <MenuItem x:Name="miAutoWrap" Header="Auto Wrap" IsCheckable="True" IsChecked="{Binding IsAutoWrap, Mode=TwoWay}">
            </MenuItem>
          </MenuItem>
        </Menu>
        <TextBox x:Name="txtContent" Grid.Row="1">
          <TextBox.Style>
            <Style TargetType="{x:Type TextBox}">
              <Style.Triggers>
                <DataTrigger Binding="{Binding IsAutoWrap}" Value="True">
                  <Setter Property="TextWrapping" Value="Wrap"/>
                </DataTrigger>
              </Style.Triggers>
            </Style>
          </TextBox.Style>
        </TextBox>
      </Grid>
    </Window>
    
    

     

    C#:

      public partial class MainWindow : Window
      {
        public MainWindow()
        {
          InitializeComponent();
          this.DataContext = new TextBoxHelper();
        }
      }
    
      public class TextBoxHelper : INotifyPropertyChanged
      {
        bool _IsAutoWrap;
        public bool IsAutoWrap
        {
          get { return _IsAutoWrap; }
          set
          {
            _IsAutoWrap = value;
            if (PropertyChanged != null)
              PropertyChanged(this, new PropertyChangedEventArgs("IsAutoWrap"));
          }
        }
    
        #region INotifyPropertyChanged Members
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        #endregion
      }
    

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年4月27日 8:22
    版主
  • Hi qing2000,

    This is WPF - Chinese forum, you could ask question in Chinese.

    As for your question, you could do actions as follow to achieve your goal:

    1) Create a Convert, like:

    public class Boolean2TextWrapping : IValueConverter

    {

        public object Convert(object value, Type targetType, object parameter, CultureInfo cultureInfo)

        {

            if (((bool)value) == false)

            {

                return TextWrapping.NoWrap;

            }

            return TextWrapping.Wrap;

        }

     

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

        {

            throw new NotImplementedException();

        }

    }

    2) add a reference, like:

    <local:Boolean2TextWrapping x:Key="Boolean2TextWrapping" />

    3) Set your control TextWrapping property, like:

    TextWrapping="{Binding ElementName=MenuItemWordWrap, Path=IsChecked, Converter={StaticResource Boolean2TextWrapping}}"

     

    Best regards,


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年4月27日 8:26
    版主

全部回复

  • TargetName 只允许在ControlTemplate中的触发器用来指定某个模板元素的属性值,不能用于Style中的触发器。

    所以你的这个需求,可以反过来设计,如果有一个中间属性,同时邦定到了这个菜单项上和TextBox的Wrap属性上,就可以实现了:

    XAML:

    <Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication2"
        Title="MainWindow" Height="350" Width="525">
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Menu>
          <MenuItem Header="Format(_F)">
            <MenuItem x:Name="miAutoWrap" Header="Auto Wrap" IsCheckable="True" IsChecked="{Binding IsAutoWrap, Mode=TwoWay}">
            </MenuItem>
          </MenuItem>
        </Menu>
        <TextBox x:Name="txtContent" Grid.Row="1">
          <TextBox.Style>
            <Style TargetType="{x:Type TextBox}">
              <Style.Triggers>
                <DataTrigger Binding="{Binding IsAutoWrap}" Value="True">
                  <Setter Property="TextWrapping" Value="Wrap"/>
                </DataTrigger>
              </Style.Triggers>
            </Style>
          </TextBox.Style>
        </TextBox>
      </Grid>
    </Window>
    
    

     

    C#:

      public partial class MainWindow : Window
      {
        public MainWindow()
        {
          InitializeComponent();
          this.DataContext = new TextBoxHelper();
        }
      }
    
      public class TextBoxHelper : INotifyPropertyChanged
      {
        bool _IsAutoWrap;
        public bool IsAutoWrap
        {
          get { return _IsAutoWrap; }
          set
          {
            _IsAutoWrap = value;
            if (PropertyChanged != null)
              PropertyChanged(this, new PropertyChangedEventArgs("IsAutoWrap"));
          }
        }
    
        #region INotifyPropertyChanged Members
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        #endregion
      }
    

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年4月27日 8:22
    版主
  • Hi qing2000,

    This is WPF - Chinese forum, you could ask question in Chinese.

    As for your question, you could do actions as follow to achieve your goal:

    1) Create a Convert, like:

    public class Boolean2TextWrapping : IValueConverter

    {

        public object Convert(object value, Type targetType, object parameter, CultureInfo cultureInfo)

        {

            if (((bool)value) == false)

            {

                return TextWrapping.NoWrap;

            }

            return TextWrapping.Wrap;

        }

     

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

        {

            throw new NotImplementedException();

        }

    }

    2) add a reference, like:

    <local:Boolean2TextWrapping x:Key="Boolean2TextWrapping" />

    3) Set your control TextWrapping property, like:

    TextWrapping="{Binding ElementName=MenuItemWordWrap, Path=IsChecked, Converter={StaticResource Boolean2TextWrapping}}"

     

    Best regards,


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年4月27日 8:26
    版主