我正在研究表达Blend for VS2015,我有ListBox
绑定到ObservableCollection
个自定义对象。这些对象暴露出Properties
出现的NotifyPropertyChanged
,一切都很好。
我可以绑定部分,如果ItemTemplate
到那些Properties
并且我的列表工作得很好但我想要做的是根据某个VisualState
设置bool
(已配置或未配置)。我还创建了一些事件(配置,confLost)并尝试在触发器面板中定位这些事件,但是没有任何效果。
如何将VisualStates
绑定到绑定对象的成员?
答案 0 :(得分:2)
ItemTemplate
属性与任何其他DependencyProperty
一样,可随时设置/重置,其视觉效果将反映在UI
上。请参阅下面的示例,其中我将bool
值绑定到ToggleButton
状态,并ItemControl's
ItemTemplate
相应地更改为 visual
强>
更新:我设计了一个Device
类,它具有设备名称和状态,可以产生类似的情况。另一个类MyVisualStateManager
用于创建可绑定属性。原因VisualStateManager
类没有公开要直接绑定的任何属性。代码如下:
<强> XMAL 强>
<Window x:Class="WpfStackOverflowTempProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"
xmlns:local="clr-namespace:WpfStackOverflowTempProject"
>
<ItemsControl ItemsSource="{Binding list}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:UserControl1 DataContext="{Binding Name}" Width="200" BorderBrush="Black" BorderThickness="2" Padding="2">
<local:UserControl1.Style>
<Style TargetType="{x:Type local:UserControl1}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext.DeviceState}" Value="0">
<Setter Property="local:MyVisualStateManager.VisualState" Value="State1" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext.DeviceState}" Value="1">
<Setter Property="local:MyVisualStateManager.VisualState" Value="State2" />
</DataTrigger>
</Style.Triggers>
</Style>
</local:UserControl1.Style>
</local:UserControl1>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<强> 用户控件: 强>
<UserControl x:Class="WpfStackOverflowTempProject.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Common">
<VisualState x:Name="State1">
<Storyboard>
<DoubleAnimation To="1" Duration="0:00:2" Storyboard.TargetName="State1Panel" Storyboard.TargetProperty="(UIElement.Opacity)" />
<DoubleAnimation To="0" Duration="0:00:3" Storyboard.TargetName="State2Panel" Storyboard.TargetProperty="(UIElement.Opacity)" />
</Storyboard>
</VisualState>
<VisualState x:Name="State2">
<Storyboard>
<DoubleAnimation To="0" Duration="0:00:3" Storyboard.TargetName="State1Panel" Storyboard.TargetProperty="(UIElement.Opacity)" />
<DoubleAnimation To="1" Duration="0:00:2" Storyboard.TargetName="State2Panel" Storyboard.TargetProperty="(UIElement.Opacity)" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border Name="State2Panel" Background="Green" Opacity="0"/>
<Border Name="State1Panel" Background="Red" Opacity="1"/>
<TextBlock Text="{Binding Path=.}" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<强> 的DataContext: 强>
public partial class MainWindow : Window
{
public MainWindow()
{
list = new List<Device>();
list.Add(new Device() {Name="Device 1",DeviceState = 0 });
list.Add(new Device() { Name = "Device 2", DeviceState = 1 });
list.Add(new Device() { Name = "Device 3", DeviceState = 0 });
list.Add(new Device() { Name = "Device 4", DeviceState = 2 });
list.Add(new Device() { Name = "Device 5", DeviceState = 1 });
InitializeComponent();
}
public List<Device> list { get; set; }
}
public class Device : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
updateProperty("Name");
}
}
private int deviceState;
public int DeviceState
{
get { return deviceState; }
set
{
deviceState = value;
updateProperty("DeviceState");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void updateProperty(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
帮助程序类: 此类公开了可绑定到VisualState
中任何值的附加属性xaml
。
public class MyVisualStateManager
{
public static string GetVisualState(DependencyObject obj)
{
return (string)obj.GetValue(VisualStateProperty);
}
public static void SetVisualState(DependencyObject obj, string value)
{
obj.SetValue(VisualStateProperty, value);
}
// Using a DependencyProperty as the backing store for VisualState. This enables animation, styling, binding, etc...
public static readonly DependencyProperty VisualStateProperty =
DependencyProperty.RegisterAttached("VisualState", typeof(string), typeof(MyVisualStateManager), new PropertyMetadata(new PropertyChangedCallback(VisualStateChanged)));
public static void VisualStateChanged(DependencyObject Do, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != null)
{
string state = e.NewValue.ToString();
var control = Do as FrameworkElement;
VisualStateManager.GoToState(control, state, true);
}
}
}
<强> 输出 强>
<强> Different Item representing different devices and visual is changed on basis of their
{Devicestate {1}}触发property which causes a
的UserControl1 to get executed in
强>
答案 1 :(得分:1)
尽管Kylo的解决方案可行,但微软的人们已经开始使用无代码,3次点击的解决方案来完成这样一个简单的操作。
解决方案是在行为上,有一个名为GoToStateAction
的行为,您必须将其中一个添加到您的控件中,您可以设置触发器(可以设置为DataTrigger)。在我的情况下,我绑定到枚举类型的属性。
然后你可以设置比较和值(等于“ReadyToUse”)
然后作为比较的结果,您可以触发特定对象的状态更改,设置对象,并从一个漂亮的组合框中选择状态。甚至还有一个用于使用转换的checbox。
答案 2 :(得分:0)
我的意思是在Blend的用户界面中,点击以获得有条件的工作,
Objects and Timeline
面板。 TextBox
。 Edit Style
创建新样式(最有可能)或Edit a Copy
,其中包含任何现有的继承样式。从那里可以使用属性选项卡来更改细节。很可能您将直接在xaml中进行特定操作。
即使是第2版的这些文档,它们仍然适用,如果没有其他任何内容可以为您提供Blend的概述