• 2018-2-13-wpf-绑定-TextLength-


    title author date CreateTime categories
    wpf 绑定 TextLength
    lindexi
    2018-2-13 17:23:3 +0800
    2018-2-13 17:23:3 +0800
    WPF

    我看到朋友的代码出现绑定了 一个 TextBlock 的 Text 的 length ,那时候我觉得 length 不是依赖属性,绑定了是无法通知的。最后我做了实验才发现,原因有 Text 可以通知。

    请看简单的代码,界面就是一个 TextBlock 和两个按钮,其中一个按钮是绑定了 length 如果大于 0 才可以使用。一个按钮是把 TextBlock 的文字设置为空或者设置为任意字符串。

        <Grid>
            <Grid.Resources>
                <local:LengthToBoolenConverter x:Key="LengthToBoolenConverter"/>
            </Grid.Resources>
            <Grid.RowDefinitions>
                <RowDefinition Height="79*"/>
                <RowDefinition Height="28*"/>
            </Grid.RowDefinitions>
            <TextBlock x:Name="TitleBlock" Margin="0,0,-0.6,-0.2" ></TextBlock>
            <Grid Grid.Row="1">
                <Button Margin="10,10,10,10" HorizontalAlignment="Left" Content="确定" Click="ButtonBase_OnClick"></Button>
                <Button Margin="10,10,10,10" HorizontalAlignment="Right" IsEnabled="{Binding ElementName=TitleBlock,Path=Text.Length,Converter={StaticResource LengthToBoolenConverter}}" Content="确定"></Button>
            </Grid>
        </Grid>
    
          public class LengthToBoolenConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                var length = (int?) value;
                return length > 0;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    
                private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
            {
                if (string.IsNullOrEmpty(TitleBlock.Text))
                {
                    TitleBlock.Text = "1";
                }
                else
                {
                    TitleBlock.Text = "";
                }
            }

    看到IsEnabled="{Binding ElementName=TitleBlock,Path=Text.Length,Converter={StaticResource LengthToBoolenConverter}}" 绑定就是 Text.Length ,但是 Length 不是依赖属性,没有通知,那么在 Text 变化时是否会通知?会的,因为使用的是 Text 的 Length,所以在 Text 修改时就会改变了 Length 。

    如果有一个 Model 类,这个类是没有继承通知的,那么如何在里面的属性修改时,可以通知?一个方法就是在 ViewModel 使用 Model 属性,每次都是修改整个 Model

        class Model
        {
            public string Foo { set; get}
            //其他就不写了
        }
    
        class ViewModel : INotifyPropertyChanged
        {
            public void Foo()
            {
                var model = new Model()
                {
                    Foo = Model.Foo,
                    //复制所有属性
                };
                model.Foo = "新的";
                Model = model;
            }
    
            private Model _model;
    
            public Model Model
            {
                get { return _model; }
                set
                {
                    _model = value;
                    OnPropertyChanged();
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }

    这样可以不修改 Model 就可以在修改属性通知,但是可以看到这需要复制所有属性,不过我有写了C# 使用Emit深克隆使用这个就可以做快复制,而且还是深复制,但是复制不是真的深,代码复制是一层,如果需要实现真的复制,还需要自己去写

    那么不复制是否可以做?可以,只需要调用OnPropertyChanged

    请把上面的代码做修改,添加一个函数,这个函数更新会自动通知。

            public void Foo(string str)
            {
                Model.Foo = str;
                OnPropertyChanged(nameof(Model));
            }

    在按钮点击就把代码修改为

            private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
            {
                if (string.IsNullOrEmpty(TitleBlock.Text))
                {
                    ViewModel.Foo("1");
                }
                else
                {
                    ViewModel.Foo("");
                }
            }

    需要添加一些绑定,请看代码

            public ViewModel ViewModel { get; set; } = new ViewModel();
    

    设置了 DataContext 之后就可以在界面绑定,这时可以看到和直接设置TextBlock的文字看起来是一样

            <TextBlock x:Name="TitleBlock" Margin="0,0,-0.6,-0.2" Text="{Binding Model.Foo}"></TextBlock>
    

    源代码:[免费]WpfTextLengthdc-CSDN下载

    博客园博客只做备份,博客发布就不再更新,如果想看最新博客,请到 https://blog.lindexi.com/

    知识共享许可协议
    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名[林德熙](http://blog.csdn.net/lindexi_gd)(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我[联系](mailto:lindexi_gd@163.com)。
  • 相关阅读:
    AJax 源码思路
    C语言博客作业--字符数组
    C语言博客作业--一二维数组
    C语言博客作业--数据类型
    C语言博客作业--函数
    C语言博客作业--嵌套循环
    C语言第三次博客作业---单层循环结构
    C语言第二次博客作业---分支结构
    C语言第一次博客作业——输入输出格式
    C语言博客作业--数据类型
  • 原文地址:https://www.cnblogs.com/lindexi/p/12085594.html
Copyright © 2020-2023  润新知