目前我有一个布尔依赖属性,它以下列方式绑定:
public bool Status
{
get { return (bool)GetValue(StatusProperty); }
set { SetValue(StatusProperty, value); }
}
public static readonly DependencyProperty StatusProperty =
DependencyProperty.Register("Status", typeof(bool),
typeof(UIButton), new PropertyMetadata(false));
我在这样的触发器中使用..
....
<Condition Binding="{Binding Path=Status}" Value="True" />
....
一切正常,但现在我想将这个布尔依赖属性扩展为类似的东西:
public class State : DependencyObject
{
public bool? status
{
get { return (bool?)GetValue(statusProperty); }
set { SetValue(statusProperty, value); }
}
public static readonly DependencyProperty statusProperty =
DependencyProperty.Register("status", typeof(bool?),
typeof(UIButton), new PropertyMetadata(false));
public State()
{
}
public State(bool status)
{
this.status = status;
}
public override string ToString()
{
if (status)
return "activated"; // this strings change on runtime, depending on user language.. simplified for demonstration purpose
else
return "deactivated"; // this strings change on runtime, depending on user language.. simplified for demonstration purpose
}
}
我的目标是,覆盖布尔对象的ToString方法,换句话说,如果我将此依赖属性绑定到像这样的文本框,则添加自定义文本
<TextBlock Text="{Binding Path=Status.status}"/>
但仍然可以在我的触发器中使用它,如上所示。
使用当前代码我正在获取XAML解析异常...不确定此构造是否有效..我认为不是。 :P
关于如何实现此类功能的任何想法?
感谢。
修改
目前我正在使用此解决方案:
public class State
{
public bool? status { get; set; }
public string statusString {
get {
if (status == true)
return "activated";
else if (status == false)
return "deactivated";
else
return "";
}
set {}
}
public State()
{
}
public State(bool? status)
{
this.status = status;
}
}
使用以下绑定:
<TextBlock Text="{Binding Path=Status.statusString}"/>
和
<Condition Binding="{Binding Path=Status.status}" Value="False" />
这很有效,唯一的缺点是,我需要在改变状态时完全交换整个对象。
myState = new State(false);
而不是......
myState.status = false;
答案 0 :(得分:1)
您是否考虑过使用自定义转换器?它将转换依赖项属性的值,但是您定义了它。您的案例中的一个例子可能是:
public class StatusToTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
try
{
bool? b = (bool?)value;
if (b == true) return "activated";
else if (b == false) return "deactivated";
else return "not set";
}
catch (Exception)
{
return "invalid";
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
try
{
bool? returnValue = null;
string s = (string)value;
if (s == "activated") returnValue = true;
else if (s == "deactivated") returnValue = false;
return returnValue;
}
catch (Exception)
{
return null;
}
}
}
然后,在您的XAML中将StatusToTextConverter定义为资源,并在TextBlock上的绑定表达式中使用转换器:
<UserControl.Resources>
<local:StatusToTextConverter x:Key="statusToTextConverter"/>
</UserControl.Resources>
<TextBlock Text="{Binding Path=Status, Converter="{StaticResource statusToTextConverter"}"/>
这样你的触发条件仍将绑定到bool属性,但TextBlock会将bool值显示为有意义的内容。
编辑:我写过这个解决方案,想要将它绑定到TextBox,而不是TextBlock。如果您只是显示值,则不需要在ConvertBack方法中定义任何内容,只需抛出NotImplementedException。答案 1 :(得分:0)
这是你的解决方案;
public class State : UIElement
{
public State()
{
}
private bool _status;
public bool Status
{
get { return (bool)GetValue(StatusProperty); }
set
{
SetValue(StatusProperty, value);
if (value != _status)
{
_status = value;
if (value)
{
this.StatusText = "Activated";
}
else
{
this.StatusText = "Deactivated";
}
RaiseStatusChangedEvent();
}
}
}
// Using a DependencyProperty as the backing store for Status. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StatusProperty =
DependencyProperty.Register("Status", typeof(bool), typeof(State), new PropertyMetadata(InternStatusChanged));
static void InternStatusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Nullable<bool> value = e.NewValue as Nullable<bool>;
if (value.HasValue)
{
((State)d).Status = value.Value;
}
}
public string StatusText
{
get { return (string)GetValue(StatusTextProperty); }
set { SetValue(StatusTextProperty, value); }
}
// Using a DependencyProperty as the backing store for StatusText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StatusTextProperty =
DependencyProperty.Register("StatusText", typeof(string), typeof(State), new PropertyMetadata(""));
// Create a custom routed event by first registering a RoutedEventID
// This event uses the bubbling routing strategy
public static readonly RoutedEvent StatusChangedEvent = EventManager.RegisterRoutedEvent(
"StatusChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(State));
// Provide CLR accessors for the event
public event RoutedEventHandler StatusChanged
{
add { AddHandler(StatusChangedEvent, value); }
remove { RemoveHandler(StatusChangedEvent, value); }
}
// This method raises the SelectedPathChanged event
void RaiseStatusChangedEvent()
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(State.StatusChangedEvent);
RaiseEvent(newEventArgs);
}
}
测试:
public partial class MainWindow : Window
{
State state;
public MainWindow()
{
InitializeComponent();
state = new State();
state.StatusChanged += new RoutedEventHandler(state_StatusChanged);
state.Status = true;
}
void state_StatusChanged(object sender, RoutedEventArgs e)
{
MessageBox.Show(this.state.StatusText);
}
}