سؤال

ولدي هذا التوصيف:

   <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>

في التعليمات البرمجية خلف لدي هذا الخط في طريقة window_loaded:

DataContext = uiManager;

وuiManager هو من نوع UIManager أن اثنين من الممتلكات العامة يدعى IsConnected وIsLoggedIn.

وفشل هذا الرمز في عند بدء التشغيل لأنه لم يتم ملأ مجموعة القيم في تحويل التي يتم استدعاؤها من قبل Multibinding مع القيم المنطقية ولكن لديها قيمة DependencyProperty.UnsetValue.

عند يمكنني استخدام الترميز أدناه (وتغيير returntype من المحول) أنه لا عمل.

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

ويبدو أن مجموعة ملزمة من خلال DataContext في رمز فشل وراء في المثال الأول، ولكنه يعمل في ثانية واحدة. لماذا؟

لاكتمال تحت الطبقة UIManager:

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
    }

وتحرير: طريقة التحويل لXAML الفشل (أنه فشل في التحويل إلى منطقي من القيم [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;
        }

ول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;
        }
هل كانت مفيدة؟

المحلول

والمشكلة لا علاقة له مع MultiBinding أو تحويل الخاص بك لا شيء. DependencyProperty.UnsetValue يعني أن الربط حصلت على أي قيمة. والواقع إذا قمت بتشغيل في وضع التصحيح يمكنك ان ترى الأخطاء ملزمة في إطار Output:

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')

لذلك دعونا تبسيط العلامات قليلا، وتطبيق بعض التشخيص:

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

وتطبيق PresentationTraceSources.TraceLevel تعلق الملكية التبعية ينتج بعض أكثر الإخراج:

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')

ونحن نرى أن الربط لا يجد DataContext والربط فشل. عندما أقوم بتغيير منشئ النوافذ بحيث يتم تعيين هذا DataContext قبل تهيئة محتوى الأعمال ملزمة:

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

ما هو غريب منذ لربط في أماكن أخرى هذا لا يهم. لا يدري لماذا لا يعمل هناك حتى أتمكن من تقديم الحلول فقط. ما يصلح مثال على ذلك هو خلق الفرشاة كمورد مع الارتباطات (يمكن هذا المورد أيضا أن تكون المحلي إلى GroupBox):

<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>

وأود أن أقترح على الرغم من أن يسقط MultiBinding والقيام ببعض ما قبل المعالجة في DataContext إذا الطبقة UIManager الخاص بك هو نوع من MVVM ViewModel.

نصائح أخرى

ونظريتي. اللون هو البنية (لا يمكن أن تكون فارغة)، لذلك SolidColorBrush.Color = فارغة من الخطأ. لا يمكن WPF إنشاء SolidColorBrush، وتحصل على استثناء.

 <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 هو كائن (يمكن أن تكون فارغة)، لذلك GroupBox.BorderBrush = فارغة على ما يرام.

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

وهذا SolidColorBrush ليس كائن ولكن FACTORY. يتم إنشاء مثيل إلا عند الحاجة، وعند هذه النقطة لديك بالفعل المرفقة DataContext.

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

و2 سنتا فقط بلدي.

وقراءة مقالتي، راجع للشغل، يمكن أن تكون مفيدة إذا كنت بحاجة الى بعض الربط غريبة أو متحركة مع محولات غريبة. http://www.codeproject.com/KB/WPF/BindingHub.aspx

وانها لأسباب مثل هذه التي قد ترغب في النظر في MVVM التعلم. هذا النمط يساعدك على ملخص نموذج والارتباطات بحيث لا تضطر إلى الاعتماد بدرجة كبيرة على المرحلين - يمكنك ببساطة ربط خاصية الإبلاغ عنها في طريقة عرض نموذج بدلا

وهناك العديد من المواد الممتازة على MVVM، لذلك أود أن أقترح عليك أن تبدأ من خلال قراءة أعمال كارل Shifflett، جوش سميث، مارلون غريش وساشا الحلاق.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top