Frage

Ich habe dieses Markup:

   <GroupBox BorderThickness="2">
    <GroupBox.BorderBrush>
        <SolidColorBrush x:Name="Border">
            <SolidColorBrush.Color>
                <MultiBinding Converter="{StaticResource ConnectionAndLoggedInToBorderBrush}">
                    <Binding Path="IsConnected"/>
                    <Binding Path="IsLoggedIn"/>
                </MultiBinding>
            </SolidColorBrush.Color>
        </SolidColorBrush>
    </GroupBox.BorderBrush>

Im Code hinter ich diese Zeile in der Window_Loaded Methode habe:

DataContext = uiManager;

UIManager ist vom Typ UIManager, die zwei öffentliche Eigenschaften genannt IsConnected und IsLoggedIn hat.

Dieser Code nicht bei beim Start, da die Werte Array in dem Konverter, die von der mehrbindigen genannt wird mit booleans nicht gefüllt ist, aber einen Wert von DependencyProperty.UnsetValue.

Wenn ich das Markup unten (und den Rückgabetyp des Wandlers ändern) es funktioniert.

   <GroupBox BorderThickness="2">
    <GroupBox.BorderBrush>
         <MultiBinding Converter="{StaticResource ConnectionAndLoggedInToBorderBrush}">
              <Binding Path="IsConnected"/>
              <Binding Path="IsLoggedIn"/>
         </MultiBinding>
    </GroupBox.BorderBrush>

Es scheint, dass die Bindung Satz durch den Datacontext in der Code-behind im ersten Beispiel ausfällt, funktioniert aber in dem zweiten. Warum?

Für Vollständigkeit unter der UIManager Klasse:

public class UIManager:IUIManager
    {

        #region Implementation of IUIManager

        private const string IsLoggedInProperty = "IsLoggedIn";
        private bool loggedIn;
        private readonly object loggedInLock = new object();
        public bool IsLoggedIn
        {
            get
            {
                lock (loggedInLock)
                {
                    return loggedIn;
                }
            }
            set
            {
                lock (loggedInLock)
                {
                    if(value==loggedIn)return;
                    loggedIn = value;
                    OnPropertyChanged(IsLoggedInProperty);
                }
            }
        }

        private void OnPropertyChanged(string property)
        {
            if(PropertyChanged!=null)PropertyChanged(this,new PropertyChangedEventArgs(property));
        }

        private const string IsConnectedProperty = "IsConnected";
        private bool isConnected;
        private object isConnectedLock = new object();
        public bool IsConnected
        {
            get
            {
                lock (isConnectedLock)
                {
                    return isConnected;
                }
            }
            set
            {
                lock (isConnectedLock)
                {
                    if(value==isConnected)return;
                    isConnected = value;
                    OnPropertyChanged(IsConnectedProperty);
                }
            }
        }

        #endregion

        #region Implementation of INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }

EDIT: Das Umwandlungsverfahren für das fehlerhafte XAML (es nicht auf der Umstellung auf Bool von Werten [0]:

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            var is_connected = (bool) values[0];
            var is_loggedin = (bool) values[1];
            return is_loggedin
                       ? is_connected
                             ? Colors.YellowGreen
                             : Colors.Red
                       : Colors.Gray;
        }

für das Arbeits XAML:

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            var is_connected = (bool) values[0];
            var is_loggedin = (bool) values[1];
            return is_loggedin
                       ? is_connected
                             ? Brushes.YellowGreen
                             : Brushes.Red
                       : Brushes.Gray;
        }
War es hilfreich?

Lösung

Das Problem hat nichts mit einem MultiBinding oder Ihren Konverter zu tun. DependencyProperty.UnsetValue bedeutet, dass die Bindung keinen Wert hätte. Und in der Tat, wenn Sie im Debug-Modus ausführen können Sie Bindung Fehler im Output Fenster:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=IsConnected; DataItem=null; target element is 'SolidColorBrush' (HashCode=17654054); target property is 'Color' (type 'Color')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=IsLoggedIn; DataItem=null; target element is 'SolidColorBrush' (HashCode=17654054); target property is 'Color' (type 'Color')

Also lassen Sie uns das Markup ein wenig vereinfachen und einige Diagnose anwenden:

<GroupBox>
    <GroupBox.BorderBrush>
        <SolidColorBrush>
            <SolidColorBrush.Color>
                <Binding Path="GroupColor" PresentationTraceSources.TraceLevel="High"/>
            </SolidColorBrush.Color>
        </SolidColorBrush>
    </GroupBox.BorderBrush>
</GroupBox>

Sie die beigefügte Abhängigkeitseigenschaft PresentationTraceSources.TraceLevel Anwendung ergibt etwas mehr Leistung:

System.Windows.Data Warning: 52 : Created BindingExpression (hash=17654054) for Binding (hash=44624228)
System.Windows.Data Warning: 54 :   Path: 'GroupColor'
System.Windows.Data Warning: 56 : BindingExpression (hash=17654054): Default mode resolved to OneWay
System.Windows.Data Warning: 57 : BindingExpression (hash=17654054): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 58 : BindingExpression (hash=17654054): Attach to System.Windows.Media.SolidColorBrush.Color (hash=52727599)
System.Windows.Data Warning: 60 : BindingExpression (hash=17654054): Use Framework mentor <null>
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source 
System.Windows.Data Warning: 65 : BindingExpression (hash=17654054): Framework mentor not found
System.Windows.Data Warning: 61 : BindingExpression (hash=17654054): Resolve source deferred
System.Windows.Data Warning: 91 : BindingExpression (hash=17654054): Got InheritanceContextChanged event from SolidColorBrush (hash=52727599)
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source 
System.Windows.Data Warning: 66 : BindingExpression (hash=17654054): Found data context element: GroupBox (hash=51393439) (OK)
System.Windows.Data Warning: 67 : BindingExpression (hash=17654054): DataContext is null
System.Windows.Data Warning: 91 : BindingExpression (hash=17654054): Got InheritanceContextChanged event from SolidColorBrush (hash=52727599)
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source 
System.Windows.Data Warning: 65 : BindingExpression (hash=17654054): Framework mentor not found
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source 
System.Windows.Data Warning: 65 : BindingExpression (hash=17654054): Framework mentor not found
System.Windows.Data Warning: 63 : BindingExpression (hash=17654054): Resolving source  (last chance)
System.Windows.Data Warning: 65 : BindingExpression (hash=17654054): Framework mentor not found
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=GroupColor; DataItem=null; target element is 'SolidColorBrush' (HashCode=52727599); target property is 'Color' (type 'Color')

Wir sehen, dass die Bindung versagt keine DataContext und die Bindung finden. Wenn ich die Konstrukteurs-Fenster ändern, so dass DataContext vor der Initialisierung des Inhalts der Bindung ab Werk festgelegt:

public Window1()
{
    DataContext = ...;
    InitializeComponent();
}

Was da für Bindungen an anderen Orten seltsam ist dies keine Rolle spielt. Nicht sicher, warum es nicht, dass es funktioniert, damit ich nur Abhilfen anbieten kann. Was zum Beispiel funktioniert, ist die Bürste als Ressource mit den Bindungen zu schaffen (die Ressource auch lokal auf den GroupBox sein könnte):

<GroupBox BorderBrush="{DynamicResource resbrush}">
    <GroupBox.Resources>
        <SolidColorBrush x:Key="resbrush">
            <SolidColorBrush.Color>
                <MultiBinding Converter="{StaticResource ConnectionAndLoggedInToBorderBrush}">
                    <Binding Path="IsConnected"/>
                    <Binding Path="IsLoggedIn"/>
                </MultiBinding>
            </SolidColorBrush.Color>
        </SolidColorBrush>
    </GroupBox.Resources>
</GroupBox>

Ich würde vorschlagen, obwohl die MultiBinding fallen zu lassen und eine Vorbearbeitung im DataContext wenn Ihre UIManager Klasse ist eine Art von MVVM ViewModel zu tun.

Andere Tipps

Meine Theorie. Die Farbe ist struct (kann nicht null sein), so SolidColorBrush.Color = null falsch ist. WPF können SolidColorBrush nicht erstellen, und Sie Ausnahme erhalten.

 <GroupBox.BorderBrush>
     <SolidColorBrush x:Name="Border">
         <SolidColorBrush.Color>
             <MultiBinding Converter="{StaticResource 
                           ConnectionAndLoggedInToBorderBrush}">
                 <Binding Path="IsConnected"/>
                 <Binding Path="IsLoggedIn"/>
             </MultiBinding>
         </SolidColorBrush.Color>
     </SolidColorBrush>
 </GroupBox.BorderBrush>

BorderBrush ist Objekt (kann null sein), so GroupBox.BorderBrush = null ist OK.

 <GroupBox.BorderBrush>
      <MultiBinding Converter="{StaticResource 
                    ConnectionAndLoggedInToBorderBrush}">
           <Binding Path="IsConnected"/>
           <Binding Path="IsLoggedIn"/>
      </MultiBinding>
 </GroupBox.BorderBrush>

Dieses SolidColorBrush ist kein Objekt, sondern eine Fabrik. Es wird nur instanziiert, wenn nötig, und an diesem Punkt haben Sie bereits Datacontext angebracht ist.

 <GroupBox.Resources>
      <SolidColorBrush x:Key="resbrush">
           <SolidColorBrush.Color>
                <MultiBinding Converter="{StaticResource 
                              ConnectionAndLoggedInToBorderBrush}">
                     <Binding Path="IsConnected"/>
                     <Binding Path="IsLoggedIn"/>
                </MultiBinding>
           </SolidColorBrush.Color>
      </SolidColorBrush>
 </GroupBox.Resources>

Just my 2 cents.

Lesen Sie meinen Artikel könnte btw, nützlich sein, wenn Sie einige seltsame Bindungen oder Animationen mit seltsamen Converters müssen. http://www.codeproject.com/KB/WPF/BindingHub.aspx

Es ist aus Gründen wie diese, die Sie vielleicht lernen MVVM zu betrachten. Dieses Muster hilft Ihnen, zu abstrahieren das Modell und Bindungen, so dass Sie müssen nicht verlassen so stark auf DPs -. Sie einfach auf eine meldepflichtig Eigenschaft in einem View-Modell binden können stattdessen

Es gibt mehrere ausgezeichnete Artikel über MVVM, also würde ich Sie durch das Lesen der Werke von Karl Shifflett, Josh Smith, Marlon Grech und Sacha Barber beginnen vor.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top