C# 如何在XAML、WPF中通过数据绑定设置VisualState初始化
我想知道我能用XAML做些什么,用正确的VisualState初始化我的UI元素没有代码隐藏。因为我知道如何使用C代码 我的UI元素的XAML是这样的:C# 如何在XAML、WPF中通过数据绑定设置VisualState初始化,c#,wpf,xaml,C#,Wpf,Xaml,我想知道我能用XAML做些什么,用正确的VisualState初始化我的UI元素没有代码隐藏。因为我知道如何使用C代码 我的UI元素的XAML是这样的: <Border x:Name="PART_Border" > <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CriticalnessStates"> <VisualSta
<Border x:Name="PART_Border" >
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CriticalnessStates">
<VisualState x:Name="NonCritical"/>
<VisualState x:Name="Critical"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<i:Interaction.Triggers>
<ei:DataTrigger Binding="{Binding IsCritical}" Value="False">
<ei:GoToStateAction StateName="NonCritical"/>
</ei:DataTrigger>
<ei:DataTrigger Binding="{Binding IsCritical}" Value="True">
<ei:GoToStateAction StateName="Critical"/>
</ei:DataTrigger>
</i:Interaction.Triggers>
</Border>
public class VisualStateCondition
{
/// <summary>
/// The PropertyName to look for in the associated object's <see cref="FrameworkElement.DataContext"/>.
/// </summary>
public string PropertyName { get; set; }
/// <summary>
/// The Value to check for equality.
/// </summary>
public object Value { get; set; }
/// <summary>
/// The <see cref="VisualState.Name"/> that is desired for the condition.
/// </summary>
public string DesiredState { get; set; }
}
加载UI元素后,如果设置了IsCritical属性,则它可以很好地工作,但问题是,我需要将元素加载到正确的VisualState中;我是说
IsCritical=true=>处于临界状态的元件负载IsCritical=false=>非临界状态下的元素加载 通过C#代码隐藏文件,您可以为元素编写一个已加载的事件处理程序,通过检查相应的DataContext属性来设置可视状态。我想知道如何用纯XAML实现这一点 顺便说一下,ei和i指向以下XML名称空间: xmlns:i=”http://schemas.microsoft.com/expression/2010/interactivity“xmlns:ei=”http://schemas.microsoft.com/expression/2010/interactions"
谢谢。
IsCritical
是一个源属性,应该在视图模型或控件本身中以编程方式实现和设置。因此,应该在视图模型中或在实现属性的任何位置设置默认值
样式
或数据触发器
无法设置视图模型属性的值
另外,控件的实现应该定义它所处的视觉状态。您可以通过在控制类中以编程方式调用
VisualStateManager.GoToState
来实现这一点。我实现了这个行为类:
using System;
using System.Windows;
using System.Collections.Generic;
using System.Windows.Interactivity;
using System.Windows.Markup;
[ContentProperty("Conditions")]
public class VisualStateInitializer : Behavior<FrameworkElement>
{
private bool _useTransitions = true;
public bool UseTransitions
{
get { return _useTransitions; }
set { _useTransitions = value; }
}
public List<VisualStateCondition> Conditions { get; set; }
public VisualStateInitializer()
{
Conditions = new List<VisualStateCondition>();
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += AssociatedObject_Loaded;
}
protected override void OnDetaching()
{
base.OnDetaching();
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
if (AssociatedObject.DataContext == null)
return;
foreach (var item in Conditions)
{
var dataContextType = AssociatedObject.DataContext.GetType();
System.Reflection.PropertyInfo propertyInfo;
object value = null;
var properties = item.PropertyName.Split('.');
if (properties.Length > 1)
{
for (int i = 0; i < properties.Length; i++)
{
if(value != null)
{
dataContextType = value.GetType();
propertyInfo = dataContextType.GetProperty(properties[i]);
value = propertyInfo.GetValue(value);
}
else
{
propertyInfo = dataContextType.GetProperty(properties[i]);
value = propertyInfo.GetValue(AssociatedObject.DataContext);
}
}
}
else
{
value = AssociatedObject.DataContext.GetType().GetProperty(item.PropertyName).GetValue(AssociatedObject.DataContext);
}
if (value != null && value.Equals(item.Value))
VisualStateManager.GoToElementState(AssociatedObject, item.DesiredState, UseTransitions);
}
}
}
使用系统;
使用System.Windows;
使用System.Collections.Generic;
使用System.Windows.Interactive;
使用System.Windows.Markup;
[内容财产(“条件”)]
公共类初始值设定项:行为
{
private bool _usetransforts=true;
公共图书馆
{
获取{return}
设置{u usetransformations=value;}
}
公共列表条件{get;set;}
公共初始值设定项()
{
条件=新列表();
}
受保护的覆盖无效附加()
{
base.onatached();
AssociatedObject.Loaded+=AssociatedObject\u Loaded;
}
附加时受保护的覆盖无效()
{
base.OnDetaching();
}
已加载关联对象的私有无效(对象发送方,路由目标)
{
if(AssociatedObject.DataContext==null)
返回;
foreach(条件中的var项目)
{
var dataContextType=AssociatedObject.DataContext.GetType();
System.Reflection.PropertyInfo PropertyInfo;
对象值=空;
var properties=item.PropertyName.Split('.');
如果(properties.Length>1)
{
for(int i=0;i
而VisualStateCondition类是这样的:
<Border x:Name="PART_Border" >
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CriticalnessStates">
<VisualState x:Name="NonCritical"/>
<VisualState x:Name="Critical"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<i:Interaction.Triggers>
<ei:DataTrigger Binding="{Binding IsCritical}" Value="False">
<ei:GoToStateAction StateName="NonCritical"/>
</ei:DataTrigger>
<ei:DataTrigger Binding="{Binding IsCritical}" Value="True">
<ei:GoToStateAction StateName="Critical"/>
</ei:DataTrigger>
</i:Interaction.Triggers>
</Border>
public class VisualStateCondition
{
/// <summary>
/// The PropertyName to look for in the associated object's <see cref="FrameworkElement.DataContext"/>.
/// </summary>
public string PropertyName { get; set; }
/// <summary>
/// The Value to check for equality.
/// </summary>
public object Value { get; set; }
/// <summary>
/// The <see cref="VisualState.Name"/> that is desired for the condition.
/// </summary>
public string DesiredState { get; set; }
}
公共类VisualState条件
{
///
///要在关联对象的属性中查找的PropertyName。
///
公共字符串PropertyName{get;set;}
///
///要检查是否相等的值。
///
公共对象值{get;set;}
///
///该条件所需的参数。
///
公共字符串DesiredState{get;set;}
}
在正确的初始状态下初始化视图类所需的只是定义VisualStateConditions,如下所示:
注意=>xaml中的“i”名称空间指的是BlendSdk的“System.Windows.Interactivity”
xmlns:i=”http://schemas.microsoft.com/expression/2010/interactivity"
真的
假的
其中ViewHelpers是我的VisualStateInitializer和VisualStateCondition类的命名空间。
有人能提出更好的方法吗
更新1=>编辑属性值检索,以便我们可以传递嵌套属性,如:
<viewHelpers:VisualStateCondition PropertyName="X.Y.NestedProperty"
Value="False"
DesiredState="StateForNestedProperty"/>
IsCritical是一个源属性,应该在视图模型或控件本身中以编程方式实现和设置。您没有在XAML中设置DataTrigger的源属性。它属于您的控件类还是什么?@mm8是的,它是我的ViewModel的一个属性,应该管理状态。然后您应该在视图模型中设置该属性的默认值。看看我的答案。没有关系