2016-11-30 5 views
3

Может ли подпрограмма модели отслеживания параметров пользовательского контроля WPF автоматически переименовывать себя?Изменение рендеринга WPF на изменение модели подкатегории вида

Давайте предположим, что у меня есть модель с двумя свойствами:

public class FullName : ViewModel 
{ 
    string _first; 
    string _last; 

    public string First 
    { 
     get { return _first; } 
     set 
     { 
      _first = value; 
      RaisePropertyChanged(); 
     } 
    } 

    public string Last 
    { 
     get { return _last; } 
     set 
     { 
      _last = value; 
      RaisePropertyChanged(); 
     } 
    } 
} 

Где ViewModel является:

public abstract class ViewModel : INotifyPropertyChanged 
{ 
    protected void RaisePropertyChanged([CallerMemberName] string propertyName = null) => 
     OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) => 
     PropertyChanged?.Invoke(this, e); 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

Я хотел бы иметь Dependency Property на WPF Custom Control (AffectsRender, нет SubPropertiesDoNotAffectRender) к эталонной модели таким образом, чтобы автоматическое переключение на First и Last было изменено:

public class Tag : Control 
{ 
    public static readonly DependencyProperty FullNameProperty = 
     DependencyProperty.Register("FullName", typeof(FullName), typeof(Tag), 
      new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender)); 

    public FullName FullName 
    { 
     get { return (FullName)GetValue(FullNameProperty); } 
     set { SetValue(FullNameProperty, value); } 
    } 

    protected override void OnRender(DrawingContext drawingContext) 
    { 
     base.OnRender(drawingContext); 
     if (FullName == null) 
      return; 

     FontFamily courier = new FontFamily("Courier New"); 
     Typeface courierTypeface = new Typeface(courier, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal); 
     FormattedText ft2 = new FormattedText(FullName.First + " " + FullName.Last, 
              CultureInfo.CurrentCulture, 
              FlowDirection.LeftToRight, 
              courierTypeface, 
              14.0, 
              Brushes.Black); 

     drawingContext.DrawText(ft2, new Point()); 
    } 
} 

Вот фрагмент кода, чтобы проверить:

<Window x:Class="WpfApplication3.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:WpfApplication3" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="139.9" Width="249.514"> 
    <StackPanel> 
    <StackPanel.DataContext> 
     <local:FullName> 
      <local:FullName.First>John</local:FullName.First> 
      <local:FullName.Last>Doe</local:FullName.Last> 
     </local:FullName> 
    </StackPanel.DataContext> 
    <local:Tag FullName="{Binding}" Height="20"/> 
    <TextBox Text="{Binding First, UpdateSourceTrigger=PropertyChanged}"/> 
    <TextBox Text="{Binding Last, UpdateSourceTrigger=PropertyChanged}"/> 
    </StackPanel> 
</Window> 

К сожалению, это не работает - изменения не распространяющиеся на таможенный контроль. Можно ли это сделать эффективно? Что это за SubPropertiesDoNotAffectRender?

+0

@nkoniishvt На самом деле, пожалуйста, посмотрите на 'Tag. OnRender', который рисует 'FullName.First +" "+ FullName.Last'. Мне нужно полностью «составленный владельцем» компонент диаграммы (без шаблонов или наследования) для отображения содержимого динамически обновляемого графического объекта модели объекта. У меня сложилось впечатление, что контроль над образцами подсистемы отслеживает изменения без явного подавления 'SubPropertiesDoNotAffectRender', но это не работает. –

ответ

1

Для этой работы, ваш FullName класса должен быть Freezable и ваши First и Last свойства должно быть свойством зависимостей.

Вы могли бы взглянуть на current implementation в DependencyObject:

internal void NotifySubPropertyChange(DependencyProperty dp) 
{ 
    InvalidateSubProperty(dp); 

    // if the target is a Freezable, call FireChanged to kick off 
    // notifications to the Freezable's parent chain. 
    Freezable freezable = this as Freezable; 
    if (freezable != null) 
    { 
     freezable.FireChanged(); 
    } 
} 

Этот механизм был изначально не предназначен для наблюдения подсвойства переплетенного вида-модели. Это помогает упростить измерение, организацию и визуализацию Freezable s и инициировать соответствующие действия по изменению их свойств и под-свойств.

Вы можете найти хороший пост here блога, который объясняет, как делает сохраненную графическую систему в WPF работы и как использовать эту функцию вы заинтересованы в.

+0

Есть ли официальный способ вызвать 'NotifySubPropertyChange', когда изменяется свойство свойства« none -Freezable »? Я использовал отражение кода [здесь] (http://codereview.stackexchange.com/questions/149059/automatic-redrawing-in-wpf), но он медленный и опасный ... –

+1

@DmitryNogin, AFAIK нет никакого способа сделать это , Чтобы ускорить вызов метода через отражение, вы можете кэшировать «делегат», как описано в [этой статье] (https://codeblog.jonskeet.uk/2008/08/09/making-reflection-fly-and-exploring- делегаты /). Однако, опираясь на внутренние методы .NET Framework, не является хорошим способом написания поддерживаемого и надежного кода, поэтому я бы не рекомендовал это делать. – dymanoid

Смежные вопросы