我正在尝试绑定窗口Title属性,以便显示对象的文件名和修改状态。文件名和修改后的状态都是对象的依赖属性。
我知道我可能只是在对象中添加一个“WindowTitle”属性,但这看起来相当hacky。我已经创建了一个非常简化的版本,我正在尝试做。
这是XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="{Binding Converter={StaticResource windowTitleConverter}}" Height="195" Width="245">
<Window.Resources>
<local:WindowTitleConverter x:Key="windowTitleConverter"/>
</Window.Resources>
<Grid Height="150" Width="217">
<TextBox Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding FileName}" />
<CheckBox Content="Modified" Height="16" HorizontalAlignment="Left" Margin="12,41,0,0" Name="checkBox1" VerticalAlignment="Top" IsChecked="{Binding Modified}" />
</Grid>
代码:
using System;
using System.Globalization;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new Foo();
}
}
public class Foo : DependencyObject
{
public string FileName
{
get { return (string)GetValue(FileNameProperty); }
set { SetValue(FileNameProperty, value); }
}
public static readonly DependencyProperty FileNameProperty =
DependencyProperty.Register("FileName", typeof(string), typeof(Foo), new UIPropertyMetadata());
public bool Modified
{
get { return (bool)GetValue(ModifiedProperty); }
set { SetValue(ModifiedProperty, value); }
}
public static readonly DependencyProperty ModifiedProperty =
DependencyProperty.Register("Modified", typeof(bool), typeof(Foo), new UIPropertyMetadata(0));
}
public class WindowTitleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Foo foo = (Foo)value;
if (foo == null || foo.FileName == null)
return "Foo";
return foo.FileName + (foo.Modified ? " *" : "");
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}
答案 0 :(得分:15)
如果您移动资源下方的Title
绑定,它将起作用。我不知道为什么声明的顺序在这里很重要,但它似乎对我来说是个错误
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Height="195" Width="245">
<Window.Resources>
<local:WindowTitleConverter x:Key="windowTitleConverter"/>
</Window.Resources>
<Window.Title>
<Binding Converter="{StaticResource windowTitleConverter}"/>
</Window.Title>
<!--...-->
</Window>
<强>更新强>
您现在遇到的问题是因为Dependency Property Modified具有错误的默认值类型。它是bool类型,你将它设置为0,所以将其更改为false,它应该工作
public static readonly DependencyProperty ModifiedProperty =
DependencyProperty.Register("Modified",
typeof(bool),
typeof(Foo),
new UIPropertyMetadata(false));
<强>更新强>
直接绑定到DataContext时,我不知道有任何方法可以引发PropertyChanged
。您可以使用的一个小解决方法是绑定到名为This的属性,该属性只返回this
<Window.Title>
<Binding Path="This" Converter="{StaticResource windowTitleConverter}"/>
</Window.Title>
然后,您可以使用PropertyChangedCallback
为此
PropertyChanged
public class Foo : DependencyObject, INotifyPropertyChanged
{
public Object This
{
get { return this; }
}
public bool Modified
{
get { return (bool)GetValue(ModifiedProperty); }
set { SetValue(ModifiedProperty, value); }
}
public string FileName
{
get { return (string)GetValue(FileNameProperty); }
set { SetValue(FileNameProperty, value); }
}
public static readonly DependencyProperty FileNameProperty =
DependencyProperty.Register("FileName",
typeof(string),
typeof(Foo),
new UIPropertyMetadata(string.Empty, new PropertyChangedCallback(OnFileNameChanged)));
public static readonly DependencyProperty ModifiedProperty =
DependencyProperty.Register("Modified",
typeof(bool),
typeof(Foo),
new UIPropertyMetadata(false, new PropertyChangedCallback(OnModifiedChanged)));
private static void OnFileNameChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
Foo foo = obj as Foo;
foo.OnPropertyChanged("This");
}
private static void OnModifiedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
Foo foo = obj as Foo;
foo.OnPropertyChanged("This");
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
另一种解决方案是使用MultiBinding,这样就不需要使用This属性
了<Window.Resources>
<local:TitleMultiConverter x:Key="TitleMultiConverter"/>
</Window.Resources>
<Window.Title>
<MultiBinding Converter="{StaticResource TitleMultiConverter}">
<Binding Path="FileName"/>
<Binding Path="Modified"/>
</MultiBinding>
</Window.Title>
<强> TitleMultiConverter 强>
public class TitleMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
string fileName = values[0].ToString();
bool modified = (bool)values[1];
if (fileName == null)
return "Foo";
return fileName + (modified ? " *" : "");
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}