Wpf之Interaction.Triggers与Interaction.Behaviors

1. 使用Mvvmlight中的EventToCommand, Mvvmlight对System.Windows.Interactivity.dll的某些方面进行的扩展

view:

<StackPanel DockPanel.Dock="Top">
    <TextBlock Text="传递原事件参数" FontWeight="Bold" FontSize="12" Margin="0 5 0 5"></TextBlock>
    <DockPanel>
        <StackPanel DockPanel.Dock="Left" Width="240" Orientation="Horizontal">
            <Border BorderBrush="{StaticResource PrimaryBrush}">
                <TextBlock Text="拖拽上传" Width="100" Height="50" AllowDrop="True" 
                    Style="{StaticResource TextBlockDefaultWarning}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Drop">
                        <mvvm:EventToCommand PassEventArgsToCommand="True" Command="{Binding DropCommnad}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
                </TextBlock>
            </Border>
        </StackPanel>
        <StackPanel DockPanel.Dock="Right">
            <TextBlock Text="{Binding FilePath,StringFormat=‘获取地址:\{0\}‘}"></TextBlock>
        </StackPanel>
    </DockPanel>
</StackPanel>

viewmodel

private RelayCommand<DragEventArgs> dropCommand;

public RelayCommand<DragEventArgs> DropCommnad
{
    get
    {
        if (dropCommand == null)
        {
            dropCommand = new RelayCommand<DragEventArgs>(arg => ExecuteDrop(arg));
        }
        return dropCommand;
    }
    set { dropCommand = value; }
}

private void ExecuteDrop(DragEventArgs e)
{
    Array array = (Array) e.Data.GetData(DataFormats.FileDrop);
    FilePath = array.GetValue(0).ToString();
}
2. 使用HandyControl实现的HandyControl.Interactivity

view

<ListBoxItem>
    <hc:Interaction.Triggers>
        <hc:EventTrigger EventName="Selected">
            <hc:EventToCommand Command="{Binding MenuItemSelectCommand}" CommandParameterValue="Pages/LogPage.xaml"/>
        </hc:EventTrigger>
    </hc:Interaction.Triggers>
    <RadioButton Style="{StaticResource RadioMenuButton}" 
                 IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Mode=TwoWay}">
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
            <TextBlock  Text="&#xe663;" FontFamily="/Resources/Fonts/#iconfont" VerticalAlignment="Center"/>
            <TextBlock Margin="15 0 0 0" Text="运行日志" VerticalAlignment="Center"/>
        </StackPanel>
    </RadioButton>
</ListBoxItem>

viewmodel

public RelayCommand<string> MenuItemSelectCommand => 
    new RelayCommand<string>(x =>
    {
        //PageUri = x;
        CurrentContent = FrameContents[x];
        if (CurrentContent.DataContext is IPageVisit visit)
        {
            visit.OnEnter(ServiceLocator.Current.GetInstance<MyContext>());
        }
    });
3. 使用Interaction.Bahaviors, 下面现实一个Bahavior让ListBox滚动到当前添加内容

view

<Grid Grid.Row="1" Margin="0 0 0 12">
    <ListBox ItemsSource="{Binding Logs}" Background="Transparent" HorizontalContentAlignment="Stretch" Margin="3,3,3,3"
         ScrollViewer.CanContentScroll="True">
        <hc:Interaction.Behaviors>
            <bhv:ScrollIntoBehavior/>
        </hc:Interaction.Behaviors>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Background="Transparent">
                    <md:PackIcon Kind="{Binding icon}" Width="26" Height="26" VerticalAlignment="Center" Margin="8 0"/>
                    <TextBlock Text="{Binding content}" TextAlignment="Left" TextWrapping="Wrap" 
                               Foreground="{Binding color}" Margin="0 0 6 0" VerticalAlignment="Center" Background="Transparent"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

ScrollIntoBehavior

public class ScrollIntoBehavior: Behavior<ListBox>
{
    protected override void OnAttached()
    {
        ListBox listBox = AssociatedObject;
        // 滚动条定位在底部
        listBox.IsVisibleChanged += ListBox_IsVisibleChanged;
        ((INotifyCollectionChanged)listBox.Items).CollectionChanged += OnListBox_CollectionChanged;
    }

    protected override void OnDetaching()
    {
        ListBox listBox = AssociatedObject;
        listBox.IsVisibleChanged -= ListBox_IsVisibleChanged;
        ((INotifyCollectionChanged)listBox.Items).CollectionChanged -= OnListBox_CollectionChanged;
    }

    private void ListBox_IsVisibleChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
    {
        ListBox listBox = AssociatedObject;
        if ((bool) e.NewValue)
        {
            int count = listBox.Items.Count;
            if (count > 0)
            {
                listBox.ScrollIntoView(listBox.Items[count - 1]);
            }
        }
    }

    private void OnListBox_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        ListBox listBox = AssociatedObject;
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            // scroll the new item into view
            listBox.ScrollIntoView(e.NewItems[0]);
        }
    }
}
4. 在Mvvm下有时候需要在viewmodel与view中的控件交互/操作,可以使用绑定、Bahavior来提供一定程度的方便, vs2017/vs2019中Interaction已经独立出来一个Nuget

地址: https://github.com/Microsoft/XamlBehaviorsWpf
XamlBehaviorsWpf还有丰富的例子参考
Wpf之Interaction.Triggers与Interaction.Behaviors

Wpf之Interaction.Triggers与Interaction.Behaviors

上一篇:高效编辑器vim之自动补全


下一篇:java DecimalFormate格式化十进制数字(小数,千分号,百分比……)