none
在Converter的Convert方法如何获取绑定的ui控件的tag属性的内容 RRS feed

  • 问题


  • 一个ui控件绑定了一个后台字段,并且使用了值转换器,但在Converter的Convert方法如何获取绑定的ui控件的tag属性的内容,因为要依赖ui上的tag的内容来做其他操作



    2018年10月2日 8:21

答案

  • 這樣的需求要使用 MultiValueConverter + MultiBinding ,大概類似以下:

        public class MyData : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            private bool _state;
            public bool State
            {
                get { return _state; }
                set
                {
                    if (_state != value )
                    {
                        _state = value;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(State)));
                    }
                }
            }       
        }
    
        public class MultiConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                return $"{values[0].ToString()} {values[1].ToString()}";
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }

    <Window x:Class="WpfApp4.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:WpfApp4"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
        <Window.DataContext >
            <local:MyData />
        </Window.DataContext> 
        <Window.Resources >
            <local:MultiConverter x:Key="converter"/>
        </Window.Resources>
        <StackPanel >
            <TextBlock Tag="This is" >
                <TextBlock.Text>
                    <MultiBinding Converter="{StaticResource converter}">                 
                        <Binding RelativeSource="{RelativeSource self}" Path="Tag"/>
                        <Binding   Path="State"/>
                    </MultiBinding>
                </TextBlock.Text> 
    
            </TextBlock>
        </StackPanel>
    </Window>
    


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

    2018年10月2日 19:51
  • Hi  便携式家园,

    >>我说的重点不是判断values[1]是不是null的方法是否问题,而是如果state是对象类型,values[1]怎么样才能拿到state的值的问题。如果换成值类型,values[1]内容不再是null,就能拿到state的内容,如果换成对象类型,values[1]的内容就是空的,重点是,绑定的后台字段是对象类型,我在Convert方法从values[1]获取的内容都是null。我要怎么样才能在Convert的方法里从values[1]能拿到绑定的后台字段是对象类型的数据。

    请参照下面代码

        <GridViewColumn Header="时间" >
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Tag="key02"  >
                                        <TextBlock.Text >
                                            <MultiBinding Converter="{StaticResource GetExpandedPropertyConverter}">
                                                <Binding  Path="State"   />
                                                <Binding RelativeSource="{RelativeSource self}" Path="Tag"/> 
                                            </MultiBinding>
                                        </TextBlock.Text>
                                    </TextBlock>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
    
    

    Best Regards,

    Yong Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年10月4日 7:16
    版主

全部回复

  • 這樣的需求要使用 MultiValueConverter + MultiBinding ,大概類似以下:

        public class MyData : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            private bool _state;
            public bool State
            {
                get { return _state; }
                set
                {
                    if (_state != value )
                    {
                        _state = value;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(State)));
                    }
                }
            }       
        }
    
        public class MultiConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                return $"{values[0].ToString()} {values[1].ToString()}";
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }

    <Window x:Class="WpfApp4.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:WpfApp4"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
        <Window.DataContext >
            <local:MyData />
        </Window.DataContext> 
        <Window.Resources >
            <local:MultiConverter x:Key="converter"/>
        </Window.Resources>
        <StackPanel >
            <TextBlock Tag="This is" >
                <TextBlock.Text>
                    <MultiBinding Converter="{StaticResource converter}">                 
                        <Binding RelativeSource="{RelativeSource self}" Path="Tag"/>
                        <Binding   Path="State"/>
                    </MultiBinding>
                </TextBlock.Text> 
    
            </TextBlock>
        </StackPanel>
    </Window>
    


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

    2018年10月2日 19:51
  • 這樣的需求要使用 MultiValueConverter + MultiBinding ,大概類似以下:

        public class MyData : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            private bool _state;
            public bool State
            {
                get { return _state; }
                set
                {
                    if (_state != value )
                    {
                        _state = value;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(State)));
                    }
                }
            }       
        }
    
        public class MultiConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                return $"{values[0].ToString()} {values[1].ToString()}";
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }

    <Window x:Class="WpfApp4.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:WpfApp4"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
        <Window.DataContext >
            <local:MyData />
        </Window.DataContext> 
        <Window.Resources >
            <local:MultiConverter x:Key="converter"/>
        </Window.Resources>
        <StackPanel >
            <TextBlock Tag="This is" >
                <TextBlock.Text>
                    <MultiBinding Converter="{StaticResource converter}">                 
                        <Binding RelativeSource="{RelativeSource self}" Path="Tag"/>
                        <Binding   Path="State"/>
                    </MultiBinding>
                </TextBlock.Text> 
    
            </TextBlock>
        </StackPanel>
    </Window>


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

    你这个是实现了,但有一个问题,只能绑定的是值类型字段,如果绑定的是对象类型的字段,会在Convert方法里会抛出空引用异常,怎么解决这个问题,我的目的是想传递一个对象类型到convert方法里,用自己在Convert方法里定制的转换方法将接受的对象类型转换string或其他的值类型数据在ui上显示。
    2018年10月3日 5:12
  • 不太明白你的意思,可以貼個 Sample 上來看看嗎?

    如果你指的是 State 或 Tag 是參考型別的問題,在取用前就要先檢查是否為 null,若為 null 則做 null 處理 (給個 default value 或其他)


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/


    2018年10月3日 6:45
  • 不太明白你的意思,可以貼個 Sample 上來看看嗎?

    如果你指的是 State 或 Tag 是參考型別的問題,在取用前就要先檢查是否為 null,若為 null 則做 null 處理 (給個 default value 或其他)


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/


    class GetExpandedPropertyConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                string key = values[0].ToString();
                ObservableDictionary<string, string> dic = values[1] as ObservableDictionary<string, string>;
                if (dic.ContainsKey(key))
                {
                    return dic[key];
                }
                return "";
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
     
    <GridViewColumn Header="时间" >
             <GridViewColumn.CellTemplate>
                     <DataTemplate>
                              <TextBlock Tag="date"  >
                                       <TextBlock.Text >
                                               <MultiBinding Converter="{StaticResource GetExpandedPropertyConverter}">
                                                        <Binding RelativeSource="{RelativeSource self}" Path="Tag"/>
                                                                    <Binding   Path="State"/>
                                                          </MultiBinding>
                                                 </TextBlock.Text>
                                         </TextBlock>
                         </DataTemplate>
               </GridViewColumn.CellTemplate>
    </GridViewColumn>      


    我的意思是,如果绑定的State 不是值类型,而是Dictionary类型或者类似这类的对象类型,那么我的转换器那里的if (dic.ContainsKey(key))这一步就会抛出System.NullReferenceException:“未将对象引用设置到对象的实例。”,这个状态下,我在vs监视器里,$"{values[0].ToString()} {values[1].ToString()}"中的values[0]显示是有内容的,但values[1]确是null。如果绑定的State 不是值类型而是对象类型,values[1]就会是null,运行取values[1]就无法做我的自定义转换处理,因为根本没有内容


    2018年10月3日 9:30
  • 依照你的程式碼,你應該先判斷 values[1] 是否為 null 才決定是否要轉型並呼叫 dic[key] 吧。

    當 values[1] 是 null,dic 也會是 null,此時呼叫 dic.ContainsKey 會拋出 nullreferenceexception 是正常的。所以遇到參照類型,要先判斷是否為 null 再決定下一步如何操作。


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

    2018年10月3日 9:50
  • 依照你的程式碼,你應該先判斷 values[1] 是否為 null 才決定是否要轉型並呼叫 dic[key] 吧。

    當 values[1] 是 null,dic 也會是 null,此時呼叫 dic.ContainsKey 會拋出 nullreferenceexception 是正常的。所以遇到參照類型,要先判斷是否為 null 再決定下一步如何操作。


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

    我说的重点不是判断values[1]是不是null的方法是否问题,而是如果state是对象类型,values[1]怎么样才能拿到state的值的问题。如果换成值类型,values[1]内容不再是null,就能拿到state的内容,如果换成对象类型,values[1]的内容就是空的,重点是,绑定的后台字段是对象类型,我在Convert方法从values[1]获取的内容都是null。我要怎么样才能在Convert的方法里从values[1]能拿到绑定的后台字段是对象类型的数据。




    2018年10月3日 14:05
  • 恐怕是資料繫結沒寫好吧。我改了一下沒有問題。
    public class TestClass : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            private bool _p1;
            public bool P1
            {
                get { return _p1; }
                set
                {
                    if (_p1 != value)
                    {
                        _p1 = value;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(P1)));
                    }
                }
            }
    
            private string _p2;
            public string P2
            {
                get { return _p2; }
                set
                {
                    if (_p2 != value)
                    {
                        _p2 = value;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(P2)));
                    }
                }
            }
        }
        public class MyData : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            private TestClass _state;
            public TestClass State
            {
                get { return _state; }
                set
                {
                    if (_state != value)
                    {
                        _state = value;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(State)));
                    }
                }
            }
    
            public MyData ()
            {
                _state = new TestClass();
                _state.P1 = true;
                _state.P2 = "Test Class Item2";
            }
    
        }
    
        public class MultiConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                bool v1 = false;
                string v2 = string.Empty;
                if (values[1] is TestClass obj)
                {
                    v1 = obj.P1;
                    v2 = obj.P2; 
                }
               
    
                return $"{values[0].ToString()} { v1 } {v2}";
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }



    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

    2018年10月3日 15:04
  • 恐怕是資料繫結沒寫好吧。我改了一下沒有問題。
    public class TestClass : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            private bool _p1;
            public bool P1
            {
                get { return _p1; }
                set
                {
                    if (_p1 != value)
                    {
                        _p1 = value;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(P1)));
                    }
                }
            }
    
            private string _p2;
            public string P2
            {
                get { return _p2; }
                set
                {
                    if (_p2 != value)
                    {
                        _p2 = value;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(P2)));
                    }
                }
            }
        }
        public class MyData : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            private TestClass _state;
            public TestClass State
            {
                get { return _state; }
                set
                {
                    if (_state != value)
                    {
                        _state = value;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(State)));
                    }
                }
            }
    
            public MyData ()
            {
                _state = new TestClass();
                _state.P1 = true;
                _state.P2 = "Test Class Item2";
            }
    
        }
    
        public class MultiConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                bool v1 = false;
                string v2 = string.Empty;
                if (values[1] is TestClass obj)
                {
                    v1 = obj.P1;
                    v2 = obj.P2; 
                }
               
    
                return $"{values[0].ToString()} { v1 } {v2}";
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }



    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/


    2018年10月3日 17:58
  • 我的 Convert 是改寫為這樣
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                bool v1 = false;
                string v2 = string.Empty;
                if (values[1] is TestClass obj)
                {
                    v1 = obj.P1;
                    v2 = obj.P2; 
                }         
    
                return $"{values[0].ToString()} { v1 } {v2}";
            }
    
    在使用 values[1] 前先檢查 if (values[1] is TestClass obj)

    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

    2018年10月4日 5:35
  • Hi  便携式家园,

    >>我说的重点不是判断values[1]是不是null的方法是否问题,而是如果state是对象类型,values[1]怎么样才能拿到state的值的问题。如果换成值类型,values[1]内容不再是null,就能拿到state的内容,如果换成对象类型,values[1]的内容就是空的,重点是,绑定的后台字段是对象类型,我在Convert方法从values[1]获取的内容都是null。我要怎么样才能在Convert的方法里从values[1]能拿到绑定的后台字段是对象类型的数据。

    请参照下面代码

        <GridViewColumn Header="时间" >
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Tag="key02"  >
                                        <TextBlock.Text >
                                            <MultiBinding Converter="{StaticResource GetExpandedPropertyConverter}">
                                                <Binding  Path="State"   />
                                                <Binding RelativeSource="{RelativeSource self}" Path="Tag"/> 
                                            </MultiBinding>
                                        </TextBlock.Text>
                                    </TextBlock>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
    
    

    Best Regards,

    Yong Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年10月4日 7:16
    版主