Если переместить привязку 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>
Обновление
Проблема, которую вы получаете сейчас, заключается в том, что измененное свойство зависимости имеет неправильный тип значения по умолчанию. Он имеет тип bool, и вы устанавливаете его на 0, поэтому измените его на false, и он должен работать
public static readonly DependencyProperty ModifiedProperty =
DependencyProperty.Register("Modified",
typeof(bool),
typeof(Foo),
new UIPropertyMetadata(false));
Обновление
Я не знаю ни одного способа поднять PropertyChanged
при привязке непосредственно к DataContext. Небольшой обходной путь, который вы можете использовать, - это привязка к свойству 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, что устранит необходимость в этом свойстве
<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();
}
}