[转]Using Bindings in Styles in Silverlight

本文介绍在Silverlight中如何通过使用代理类和附加属性实现数据绑定和命令绑定,以设置UI元素的属性,如ListBoxItem的背景颜色,并响应用户双击事件。

This document comes from this blog. I think it's very useful and reposted here.

http://blogs.profitbase.com/tsenn/?p=53

One of the differences between WPF and Silverlight is that using Bindings when setting properties in styles is still not supported (SL 4). If you try to do so, your application will simply crash.
In WPF, you can do something like this;

<Style TargetType="{x:Type ListBoxItem}">
       <Setter Property="Background" Value="{Binding Path=MyColor}"/>
</Style>

Although not directly supported, you can achieve the same thing in Silverlight using attached properties. The workaround is to specify an Attached Property in the Setter Property, and then use a “proxy” in the Setter Value to set up the binding between the actual property of the UI element and the object from the data binding. This technique can also be used for things like wiring up command to react to user input, for example when a user double clicks a ListBoxItem.



The following example shows how to set the background color of a ListBoxItem through data binding, and also how to react to a double click on the item.
<ListBox x:Name="listBox1">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Path=Name}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="b:BindingBehavior.PropertyBinding">
                        <Setter.Value>
                            <b:PropertyBinding Binding="{Binding Path=BackgroundBrush}" Property="Background"/>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="b:BindingBehavior.DoubleClickCommandBinding">
                        <Setter.Value>
                            <b:CommandBinding Command="{Binding Path=DataContext.TestCommand, ElementName=LayoutRoot}"
                                              CommandParameter="{Binding}"/>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>

As you can see, both the Setter Properties have Attached Properties defined instead of the actual property names of the ListBoxItem. In the Setter Values, I have added my proxy classes where I have specified the bindings and the name of the ListBoxItem property I want a binding to apply to.

The BindingProperty proxy class is very simple and contains only two properties; one for holding the name of the property you want to bind to and one for the binding itself.

public class PropertyBinding
    {
        public Binding Binding { get; set; }
        public string Property { get; set; }
    }

The BindingBehavior class is responsible for creating the actual binding based on an instance of the PropertyBinding. It does so using reflection on the ListBoxItem to locate the dependency property specified in the Property attribute of the PropertyBinding proxy instance.

private static void OnPropertyBindingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement frameworkElement = d as FrameworkElement;
            if (frameworkElement == null)
            {
                throw new ArgumentException("The PropertyBinding behavior can only be applied to FrameworkElement types");
            }

            PropertyBinding styleBinding = e.NewValue as PropertyBinding;
            if (styleBinding != null)
            {
                string depPropName = string.Concat(styleBinding.Property, "Property");
                if (depPropName.IndexOf('.') > -1)
                {
                    int index = depPropName.LastIndexOf('.');
                    depPropName = depPropName.Substring(index);
                }
                FieldInfo dependencyPropertyField = frameworkElement.GetType().GetField(depPropName, BindingFlags.Public
                    | BindingFlags.Static
                    | BindingFlags.FlattenHierarchy);
                if (dependencyPropertyField != null)
                {
                    DependencyProperty dependencyProperty = dependencyPropertyField.GetValue(null) as DependencyProperty;
                    if (dependencyProperty != null)
                    {
                        frameworkElement.SetBinding(dependencyProperty, styleBinding.Binding);
                    }
                }
            }

        }
 
For the command binding, a similar approach is used. The CommandBinding proxy class contains a Binding property for setting the Command and CommandParameter, and then the BindingBehavior class creates the actual binding in the OnXXXChanged event handler.

public class CommandBinding
    {
        public Binding Command { get; set; }
        public Binding CommandParameter { get; set; }
    }
private static void OnDoubleClickCommandBindingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = d as FrameworkElement;
            if (element == null)
            {
                throw new InvalidOperationException("This behavior can only be applied to FrameworkElement types");
            }

            CommandBinding styleBinding = e.NewValue as CommandBinding;
            if (styleBinding != null)
            {
                element.SetBinding(BindingBehavior.DoubleClickProperty, styleBinding.Command);
                if (styleBinding.CommandParameter != null)
                {
                    element.SetBinding(BindingBehavior.DoubleClickParameterProperty, styleBinding.CommandParameter);
                }
                else
                {
                    element.ClearValue(BindingBehavior.DoubleClickParameterProperty);
                }
            }
            else
            {
                element.ClearValue(BindingBehavior.DoubleClickProperty);
                element.ClearValue(BindingBehavior.DoubleClickParameterProperty);
            }
        }

转载于:https://www.cnblogs.com/JerryWeng/archive/2011/02/25/1964893.html

<think> 嗯,用户正在面对一个在Nvidia Orin平台上进行模型部署时的技术难题:将ONNX模型换为TensorRT模型后出现推理异常。这显然是工业级AI部署中的典型痛点,尤其是边缘设备场景。 从用户提供的引用来看,ta至少已经掌握了三个关键线索:一是显存不足可能导致serialize属性缺失的错误;二是ONNX不支持的操作符会阻断换流程;三是TensorRT初始化失败的可能性。用户能精准引用这些专业文档,说明ta具备一定的工程基础,但可能缺乏Orin平台的实战经验。 考虑到Orin作为嵌入式AI芯片的特性,需要特别注意三点区别于桌面级GPU的约束:首先是严格的显存限制(通常16GB共享内存),其次ARM架构对某些算子的兼容性差异,最后是Jetson环境特有的依赖链问题。用户没有提供具体报错信息,这点稍显遗憾,但我们可以用分层排查法覆盖常见场景。 值得肯定的是用户明确标注了引用来源,这种严谨态度值得鼓励。不过ta提到的引用[3]关于自定义OP的方案,在Orin平台上实施成本较高,应该作为最后手段。优先排查路线应该从硬件资源开始,逐步过渡到软件栈适配。 突然想到Orin的TensorRT版本可能和用户开发环境存在差异。很多开发者习惯在x86服务器换模型后部署到Orin,却忽略了JetPack版本对齐问题,这个隐蔽点必须纳入解决方案。另外引用[2]提到的TVM作为备选方案值得展开,但当前阶段还是先聚焦TensorRT原生支持更高效。 用户没提及模型类型,但计算机视觉模型(如YOLO系列)在Orin上最容易遇到预处理/后处理不兼容的问题。如果异常出现在输入输出阶段,可能需要检查NHWC格式换或动态尺寸支持。不过这些属于进阶排查项,首轮建议还是以基础诊断为主。 </think> 在NVIDIA Orin平台上将ONNX模型换为TensorRT模型后出现推理异常,可参考以下分层解决方案: ### 一、基础环境排查 1. **显存与内存问题** - 执行 `free -h` 和 `nvidia-smi` 检查共享内存占用 - 尝试清空缓存: ```bash sudo sync && echo 3 | sudo tee /proc/sys/vm/drop_caches ``` - 换时添加显存优化参数(实测有效): ```python builder_config = builder.create_builder_config() builder_config.max_workspace_size = 1 << 30 # 设置1GB工作空间 ``` 2. **版本对齐** Orin平台需严格匹配组件版本: ```bash # 检查JetPack版本 cat /etc/nv_tegra_release # 确认组件版本链 dpkg -l | grep -E "TensorRT|onnx|cuDNN" ``` *典型版本组合:JetPack 5.1.2 + TRT 8.5.1 + ONNX 1.12.0* ### 二、模型换诊断 1. **OP兼容性处理** 使用Netron可视化模型,定位不支持算子: ```python # 检查ONNX算子支持情况 from onnxsim import simplify simplified_model, check = simplify(onnx_model) assert check, "简化失败:存在不支持的OP" ``` 2. **动态形状配置**(常见错误点) ```python profile = builder.create_optimization_profile() profile.set_shape("input", min=(1,3,224,224), opt=(8,3,224,224), max=(32,3,224,224)) config.add_optimization_profile(profile) ``` --- ### 三、进阶调试方案 1. **逐层精度校验** ```python # 启用详细日志 import tensorrt as trt logger = trt.Logger(trt.Logger.VERBOSE) # 构建时捕获警告 config.set_flag(trt.BuilderFlag.FP16) if use_fp16 else None config.set_flag(trt.BuilderFlag.DEBUG) # 关键!启用调试模式 ``` 2. **自定义OP处理流程** 当遇到类似报错: ```bash 'NoneType' object has no attribute 'serialize' ``` 按顺序执行: ```mermaid graph LR A[检查TRT日志] --> B{是否出现<br>“Unsupported OP_XXX”} B -->|是| C[实现TRT插件] B -->|否| D[检查输入张量维度] D --> E[验证动态尺寸配置] ``` --- ### 四、Orin平台专项优化 1. **DLA激活** ```python config.default_device_type = trt.DeviceType.DLA config.DLA_core = 0 # 指定使用DLA核心 ``` 2. **功耗墙配置** ```bash # 设置最大性能模式 sudo nvpmodel -m 0 # MAXN模式 sudo jetson_clocks ``` --- ### 验证方案 ```python # 加载TRT引擎后执行冒烟测试 with open("model.engine", "rb") as f: engine = runtime.deserialize_cuda_engine(f.read()) context = engine.create_execution_context() # 创建伪输入数据 input_host = np.ones(context.get_binding_shape(0), dtype=np.float32) input_device = cuda.mem_alloc(input_host.nbytes) cuda.memcpy_htod(input_device, input_host) # 执行推理 context.execute_v2(bindings=[int(input_device)]) ``` > ⚠️ 若此处报错,重点检查数据拷贝流程和绑定顺序 --- ### 典型错误解决方案 | 错误类型 | 解决措施 | |----------------------------------|-------------------------------------------------------------------------| | `AttributeError: serialize` | 1. 检查`builder.build_engine`返回值有效性<br>2. 降低`max_workspace_size` | | `[TRT] INTERNAL_ERROR` | 禁用`tf32`计算:`config.set_flag(trt.BuilderFlag.TF32, False)` | | `DLA not supported for layer` | 使用`config.enable_dla()`显式启用DLA | | `Invalid dimension values` | 使用`trtexec`验证输入维度:<br>`trtexec --onnx=model.onnx --shapes=input:32x3x224x224` |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值