小编Fla*_*ack的帖子

C#和Excel互操作

我的一个用户在尝试通过我的C#应用​​程序打开Excel文件时遇到问题.

当我从我的机器运行它时,一切正常,它适用于其他用户.我不是Excel互操作专家所以希望你们可以帮助我.

以下是它的设置方式:

我将我的应用程序的引用添加到Microsoft.Office.Interop.Excel.dll,版本10.0.4504.0(我相信是Excel 2002).在我的机器上,我安装了Excel 2007.在我的代码中,我尝试打开这样的工作表:

using Microsoft.Office.Interop
...
Microsoft.Office.Interop.Excel.ApplicationClass _excelApp = new Microsoft.Office.Interop.Excel.ApplicationClass();
Microsoft.Office.Interop.Excel.Workbook excelWorkbook = _excelApp.Workbooks.Open(workbookPath, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", false, false, 0, true, false, false);
Microsoft.Office.Interop.Excel.Sheets excelSheets = excelWorkbook.Worksheets;
Microsoft.Office.Interop.Excel.Worksheet excelWorksheet = (Microsoft.Office.Interop.Excel.Worksheet)excelSheets.get_Item(1);
Run Code Online (Sandbox Code Playgroud)

我将用户版本记录为Excel 9.0(即2000).用户获得的错误是:

Exception='System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at Microsoft.Office.Interop.Excel.Workbooks.Open(String Filename, Object UpdateLinks, Object ReadOnly, Object Format, Object Password, Object WriteResPassword, Object IgnoreReadOnlyRecommended, Object Origin, Object Delimiter, Object …
Run Code Online (Sandbox Code Playgroud)

c# excel interop

10
推荐指数
1
解决办法
2万
查看次数

选项卡控件默认选择第一个选项卡

我不确定这是否只是默认的WPF选项卡控件行为或是否有一种方法可以禁用它.

我有一个tab控件定义如下:

<TabControl TabStripPlacement="Left"
            Background="Transparent" 
            ItemsSource="{Binding Path=AvailableProducts}"
            SelectedValuePath="Name"
            SelectedValue="{Binding Path=SelectedProduct, Mode=TwoWay}">
Run Code Online (Sandbox Code Playgroud)

AvailableProducts是产品列表.例如:

Foo
Bar
Baz
Run Code Online (Sandbox Code Playgroud)

最初,SelectedProduct为null但是当显示选项卡控件时,它会自动选择Foo.我想要的是根本没有选择标签.

选项卡控件是否总是选择第一个选项卡?

UPDATE

我添加了一些示例代码,显示了我所描述的内容.

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TabControl SelectedIndex="1">
            <TabItem Header="TAB 1">
                <Button>TEST</Button>
            </TabItem>
            <TabItem Header="TAB 2">
                <TabControl TabStripPlacement="Left"
                            Background="Transparent" 
                            ItemsSource="{Binding Path=AvailableProducts}"
                            SelectedValuePath="Name"
                            SelectedValue="{Binding Path=SelectedProduct, Mode=TwoWay}"/>
            </TabItem>
        </TabControl>
    </Grid>
</Window>




using System.Collections.Generic;

namespace WpfApplication1
{
    public partial class MainWindow
    {
        private List<Product> _availableProducts = new List<Product>();

        public MainWindow()
        {
            SelectedProduct = null;
            InitializeComponent();
            _availableProducts.Add(new Product("Foo"));
            _availableProducts.Add(new …
Run Code Online (Sandbox Code Playgroud)

c# wpf

9
推荐指数
1
解决办法
9447
查看次数

根据属性值应用Style

使用Infragistics XamDataGrid我遇到了一种情况,我只想在设置了某个属性时才应用Style.但是,我认为这更像是一个普通的WPF /样式问题,而不是xamDataGrid特有的.

以下风格是我目前使用的.它将checkBox添加到记录选择器区域:

<Style TargetType="{x:Type igDP:RecordSelector}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type igDP:RecordSelector}">
                <CheckBox x:Name="HeaderCheckBox"
                            HorizontalAlignment="Center"
                            VerticalAlignment="Center"
                            IsChecked="{Binding Path=DataItem.IsChecked}">
                </CheckBox>
                <ControlTemplate.Triggers>
                  <Trigger Property="IsFilterRecord" Value="True">
                    <Setter TargetName="HeaderCheckBox" Property="Visibility" Value="Collapsed"/>
                  </Trigger>
                  <Trigger Property="IsAddRecord" Value="True">
                    <Setter TargetName="HeaderCheckBox" Property="Visibility" Value="Collapsed"/>
                  </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)

TargetType是RecordSelector.如果记录是筛选行或添加记录行,我不想显示复选框.

我想改变它,以便如果记录是添加记录行(IsAddRecord == true),那么根本不应用该样式.我希望添加记录行保留其默认样式.

这可能吗?

wpf infragistics xamdatagrid

8
推荐指数
1
解决办法
6081
查看次数

WPF MVVM服务层

我打算第一次按照MVVM模式编写一个WPF应用程序,但对我来说并不是很清楚.假设视图有一个"保存"按钮,当它被命中时,我需要保存我的数据的当前状态(模型).这将通过向SOAP服务发送SOAP消息来完成.

在我的MVVM设置中,这些SOAP请求/响应处理程序是否存在?每当按下保存按钮时,视图模型是否会自动调用SOAP?视图模型是否应该通知模型保存自己?也许它是另一种方式,与MVVM完全分开?

我的想法是(至少在这种特定情况下)视图模型将处理它,因为它需要在视图中禁用保存按钮,直到当前保存请求完成.

wpf mvvm

7
推荐指数
1
解决办法
2944
查看次数

滚动到单行WPF TextBox的末尾

这看起来很简单,但我无法让它发挥作用.

我有一个单行文本框,有很多文本.我想要发生的是,只要文本框获得焦点,它就会滚动到文本的末尾,以便它进入视图,光标在最后准备好接受新文本.

在文本框的GotFocus事件中,我调用textBox.ScrollToEnd().看起来所有这一切都是将光标移动到文本框的末尾,但实际上并没有将结束视图.

我错过了什么?

wpf wpf-controls

7
推荐指数
2
解决办法
9556
查看次数

在单元测试中使用WPF Dispatcher的正确方法

我试图遵循在单元测试使用WPF Dispatcher的建议,以便运行我的nUnit测试.

当我按如下所示编写单元测试时,它可以工作:

[Test]
public void Data_Should_Contain_Items()
{
    DispatcherFrame frame = new DispatcherFrame();
        PropertyChangedEventHandler waitForModelHandler = delegate(object sender, PropertyChangedEventArgs e)
        {
          if (e.PropertyName == "Data")
          {
            frame.Continue = false;
          }
        };
    _myViewModel.PropertyChanged += waitForModelHandler;
    Dispatcher.PushFrame(frame);

    Assert.IsTrue(_myViewModel.Data.Count > 0, "Data item counts do not match");
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我尝试使用DispatcherUtil的建议,它不起作用:

[Test]
public void Data_Should_Contain_Items()
{
    DispatcherUtil.DoEvents();
    Assert.IsTrue(_myViewModel.Data.Count > 0, "Data item counts do not match");
}

public static class DispatcherUtil
{
    [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    public static void DoEvents()
    { …
Run Code Online (Sandbox Code Playgroud)

c# wpf nunit unit-testing dispatcher

7
推荐指数
1
解决办法
4979
查看次数

列出<T> .AddRange和yield语句

我知道yield关键字表示它出现的方法是迭代器.我只是想知道它是如何工作的List<T>.AddRange.

我们使用下面的例子:

static void Main()
{
    foreach (int i in MyInts())
    {
        Console.Write(i);
    }
}

public static IEnumerable<int> MyInts()
{  
    for (int i = 0; i < 255; i++)
    {
        yield return i;
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,在每个yield之后的上述示例中,在foreach循环中返回一个值Main并将其打印到控制台.

如果我们改为Main:

static void Main()
{
    var myList = new List<int>();
    myList.AddRange(MyInts());
}
Run Code Online (Sandbox Code Playgroud)

这是如何运作的?是否AddRange为yield语句返回的每个int调用,还是在添加整个范围之前以某种方式等待所有255个值?

.net c# foreach list

7
推荐指数
1
解决办法
990
查看次数

有没有办法找到控件的所有者线程?

我正在处理一个大型应用程序的线程问题(获得跨线程异常).有没有办法找到创建特定控件的线程名称/ ID?

当我尝试将新控件添加到控件的控件集合时,会发生错误.我不能真正创建一个小的,可重复的样本,所以我会尽可能地描述它.

我有一个位于表单上的主控件,称之为_mainControl.在它的构造函数中,我实例化了另一个控件的实例,例如

ChildControl _childControl = new ChildControl();
Run Code Online (Sandbox Code Playgroud)

现在_childControl存在但我还没有将它添加到_mainControls集合中.

最终,_mainControl会收到一个我应该添加控件的事件通知.在事件处理程序中,我检查是否.InvokeRequired,如果是,我调用处理程序,如下所示:

AddControlEventHander(...)
{
    if(InvokeRequired)
    {
        BeginInvoke(new MethodInvoker(AddControlEventHander);
        return;
    }
    Controls.Add(_childControl);
}
Run Code Online (Sandbox Code Playgroud)

Controls.Add总是抛出异常("跨线程操作无效:从创建它的线程以外的线程访问控件'_item').

现在,我不明白这是怎么回事.我在创建_mainControl的同一个线程上创建了_childControl.当我在调试时查看线程窗口时,当我调用Control.Add时,当添加_childControl时,当前线程名称/ id是相同的.但是,让我最困惑的是来自_mainControl的以下调用:

InvokeReuqired == false;
_childControl.InvokeRequired == false;
_childControl._item.InvokeRequired == true; //I made _item public just to try this and it returns true!
Run Code Online (Sandbox Code Playgroud)

怎么可能?_childControl是否有可能在一个线程上创建,而其子项以某种方式在另一个线程上创建?所有_childControl的子节点都是在初始化期间创建的,正如通常所做的那样.

如果有人对可能发生的事情有任何提示/建议,请告诉我.

谢谢.

编辑:

如果有人有兴趣,我会发现发生了什么.我很好奇如何在一个线程上创建一个控件,并且它是在另一个线程上创建的子节点,即使InitializeComponent都是在同一个线程上完成的.所以,我发现了使用类似于Charles建议的代码创建孩子的线程.一旦我知道了,我至少知道要关注哪个主题.然后我打破了子控件的OnHandleCreated事件并找到了问题.

我不知道的一件事是控件的句柄是在控件首次可见时创建的,而不是在创建控件时创建的.因此,没有控件的线程试图将其可见性设置为true.所以我添加了一个检查以查看InvokeRequired并认为这样做会有所帮助.但是,我真的没想到的是调用InvokeRequired会创建控件的句柄(如果它还没有创建)!这实际上导致在错误的线程上创建控件,并且始终为InvokeRequired返回false.我通过触摸控件的Handle属性来解决这个问题,以便在调用InvokeRequired之前创建它.

谢谢你的帮助:)

c# multithreading

6
推荐指数
1
解决办法
4271
查看次数

MVVM基础视图模型类

我正在创建一个基本视图模型类.ViewModelBase是一个抽象类,我想定义我希望所有其他派生视图模型实现的属性.

其中一个属性是ObservableCollection:

public abstract ObservableCollection<???> Items { get; set; }
Run Code Online (Sandbox Code Playgroud)

从此基类派生的类将定义不同类型的Items(ObservableCollection<Person>,ObservableCollection<Car>).

如果我将ObservableCollection类型设置为objectViewModelBase,则需要在派生类中执行大量不同的转换才能使其工作.

这是正确的方法吗?

c# mvvm

6
推荐指数
1
解决办法
7068
查看次数

修改WPF Toolkit DropDownButton样式

我试图修改WpfToolkit的DropDownButton样式,以便允许我设置背景颜色.

这是DropDownButton的默认样式:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:chrome="clr-namespace:Xceed.Wpf.Toolkit.Chromes"
                    xmlns:conv="clr-namespace:Xceed.Wpf.Toolkit.Core.Converters"
                    xmlns:local="clr-namespace:Xceed.Wpf.Toolkit">

   <conv:InverseBoolConverter x:Key="InverseBoolConverter" />

   <LinearGradientBrush x:Key="PopupDarkBorderBrush" EndPoint="0.5,1" StartPoint="0.5,0">
      <GradientStop Color="#FFA3AEB9" Offset="0" />
      <GradientStop Color="#FF8399A9" Offset="0.375" />
      <GradientStop Color="#FF718597" Offset="0.375" />
      <GradientStop Color="#FF617584" Offset="1" />
   </LinearGradientBrush>

   <LinearGradientBrush x:Key="PopupBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
      <LinearGradientBrush.GradientStops>
         <GradientStopCollection>
            <GradientStop Offset="0" Color="#FFffffff" />
            <GradientStop Offset="1" Color="#FFE8EBED" />
         </GradientStopCollection>
      </LinearGradientBrush.GradientStops>
   </LinearGradientBrush>

   <Style TargetType="{x:Type local:DropDownButton}">
      <Setter Property="BorderThickness" Value="1" />
      <Setter Property="IsTabStop" Value="False" />
      <Setter Property="HorizontalContentAlignment" Value="Center" />
      <Setter Property="VerticalContentAlignment" Value="Center" />
      <Setter Property="Padding" Value="3" />
      <Setter Property="Template">
         <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:DropDownButton}">
               <Grid x:Name="MainGrid" …
Run Code Online (Sandbox Code Playgroud)

c# wpf wpftoolkit

6
推荐指数
1
解决办法
6296
查看次数