Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自定义控件绑定不';不要更新模型_C#_Wpf_Data Binding_Dependency Properties - Fatal编程技术网

C# 自定义控件绑定不';不要更新模型

C# 自定义控件绑定不';不要更新模型,c#,wpf,data-binding,dependency-properties,C#,Wpf,Data Binding,Dependency Properties,我正在使用自定义的WindowsFormsHost控件将winforms控件包装到选项卡控件中,当用户通过DataTemplate点击“新建文档”按钮时,会动态创建选项卡 由于本文中解释的选项卡控件的限制,我的撤消/重做逻辑保留了每个选项卡的所有选项卡的历史记录,这导致显示错误的文本 因此,我决定修改FastColoredTextbox控件以公开历史记录和重做堆栈,并将它们作为依赖项属性添加到自定义WindowsFormsHost包装器控件中,该属性以两种方式绑定到我的DocumentModel

我正在使用自定义的
WindowsFormsHost
控件将winforms控件包装到选项卡控件中,当用户通过
DataTemplate
点击“新建文档”按钮时,会动态创建选项卡

由于本文中解释的选项卡控件的限制,我的撤消/重做逻辑保留了每个选项卡的所有选项卡的历史记录,这导致显示错误的文本

因此,我决定修改FastColoredTextbox控件以公开历史记录和重做堆栈,并将它们作为依赖项属性添加到自定义WindowsFormsHost包装器控件中,该属性以两种方式绑定到我的DocumentModel

XAML:


我可以通过修改自定义控件代码使UI更改模型,如下所示:

public static readonly DependencyProperty HistoryProperty = DependencyProperty.Register("History", typeof(IEnumerable<UndoableCommand>), typeof(CodeTextboxHost), new FrameworkPropertyMetadata(new ObservableCollection<UndoableCommand>(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(
    (d, e) =>
    {
        var textBoxHost = d as CodeTextboxHost;
        if (textBoxHost != null && textBoxHost._innerTextbox != null)
        {
            var history = textBoxHost.GetValue(e.Property) as ObservableCollection<UndoableCommand>;
            if (history != null)
            {
                textBoxHost._innerTextbox.TextSource.Manager.History = history.ToLimitedStack(200);
                textBoxHost._innerTextbox.OnUndoRedoStateChanged();
            }
            else
            {
                textBoxHost._innerTextbox.ClearUndo();
            }
        }
    }), null));

public static readonly DependencyProperty RedoStackProperty = DependencyProperty.Register("RedoStack", typeof(IEnumerable<UndoableCommand>), typeof(CodeTextboxHost), new FrameworkPropertyMetadata(new ObservableCollection<UndoableCommand>(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(
    (d, e) =>
    {
        var textBoxHost = d as CodeTextboxHost;
        if (textBoxHost != null && textBoxHost._innerTextbox != null)
        {
            var redoStack = textBoxHost.GetValue(e.Property) as ObservableCollection<UndoableCommand>;
            if (redoStack != null)
            {
                textBoxHost._innerTextbox.TextSource.Manager.RedoStack = redoStack.ToStack();
                textBoxHost._innerTextbox.OnUndoRedoStateChanged();
            }
            else
            {
                textBoxHost._innerTextbox.ClearUndo();
            }
        }
    }), null));

public ObservableCollection<UndoableCommand> History
{
    get { return (ObservableCollection<UndoableCommand>) GetValue(HistoryProperty);}
    set { SetCurrentValue(HistoryProperty, new ObservableCollection<UndoableCommand>(value));}
}

public ObservableCollection<UndoableCommand> RedoStack
{
    get { return (ObservableCollection<UndoableCommand>) GetValue(RedoStackProperty); }
    set { SetCurrentValue(RedoStackProperty, new ObservableCollection<UndoableCommand>(value));}
}
public static readonly dependencProperty HistoryProperty=dependencProperty.Register(“History”、typeof(IEnumerable)、typeof(CodeTextboxHost)、new FrameworkPropertyMetadata(new ObservableCollection()、FrameworkPropertyMetadata Options.bindstwoway默认情况下,new PropertyChangedCallback(
(d,e)=>
{
var textBoxHost=d作为CodeTextboxHost;
if(textBoxHost!=null&&textBoxHost.\u innerTextbox!=null)
{
var history=textBoxHost.GetValue(e.Property)作为ObservableCollection;
if(历史!=null)
{
textBoxHost.\u innerTextbox.TextSource.Manager.History=History.ToLimitedStack(200);
textBoxHost._innerTextbox.OnUndoRedoStateChanged();
}
其他的
{
textBoxHost._innerTextbox.ClearUndo();
}
}
}),空);
public static readonly dependencProperty RedoStackProperty=dependencProperty.Register(“RedoStack”、typeof(IEnumerable)、typeof(CodeTextboxHost)、new FrameworkPropertyMetadata(new ObservableCollection()、FrameworkPropertyMetadataOptions.Bindstwoway默认情况下,new PropertyChangedCallback(
(d,e)=>
{
var textBoxHost=d作为CodeTextboxHost;
if(textBoxHost!=null&&textBoxHost.\u innerTextbox!=null)
{
var redoStack=textBoxHost.GetValue(e.Property)作为ObservableCollection;
if(redoStack!=null)
{
textBoxHost._innerTextbox.TextSource.Manager.RedoStack=RedoStack.ToStack();
textBoxHost._innerTextbox.OnUndoRedoStateChanged();
}
其他的
{
textBoxHost._innerTextbox.ClearUndo();
}
}
}),空);
公众可观察的收集历史
{
get{return(ObservableCollection)GetValue(HistoryProperty);}
set{SetCurrentValue(HistoryProperty,新的ObservableCollection(value));}
}
公共可观测收集重做堆栈
{
获取{return(observeCollection)GetValue(RedoStackProperty);}
set{SetCurrentValue(RedoStackProperty,新的observeCollection(value));}
}

因此,与设置值相比,我使用
History
上的
SetCurrentValue
RedoStack
使UI正确更新模型。

使用
INotifyPropertyChanged
接口并实现
OnPropertyChanged
方法,如果我不得不猜测,将该方法放在您想更新接口的位置,我想说的是,问题开始于这样一个事实:您在模型中使用了
ObservableCollection
,在依赖属性中使用了
Stack
LimitedStack
。我只有在这些匹配的时候才有装订收藏的好运气。我总共使用了
ObservableCollection
。我无法理解完整的代码,但如果您想显式调用更新,则有一些解决方法。在文本框上尝试交互触发器文本更改它将调用一个带有参数的命令,然后您可以记录您的更改DS@Ramankingdom我实际上使用它,唯一的区别是Textbox本身是一个winforms控件,我用
WindowsFormsHost
包装它。我使用内部文本框的
TextChanged
事件来更新文本、历史记录和重做堆栈(可以在
\u innerTextbox\u TextChanged
方法中看到)。但是问题只是文本更新,其余的不会更新并存储回模型。@maykanat是调用没有传播到堆栈正在更新的代码?@Ramankingdom例如,我在DocumentModel属性更新的DocumentText中放置了一个断点。触发
TextChanged
时,
CodeTextboxHost
Text
属性将更新,在
DocumentModel
中达到断点,并且
DocumentText
属性实际上在
DocumentModel
中更新。但是,当我对
RedoStack
History
执行相同操作时,当触发
TextChanged
时,模型端不会发生任何事情,就好像用户界面没有通知
DocumentModel
一样。因此,从模型到UI的绑定是有效的,但对于
可观察集合
,情况并非如此。也许一个指向更好答案的链接会有所帮助:我不想更新UI,当前的数据绑定可以从模型到UI很好地工作。问题是,当我在可观察集合的UI中进行更新时,它不会更新模型的可观察集合。
public ObservableCollection<UndoableCommand> History
{
    get { return _history; }
    set
    {
        _history = value;
        OnPropertyChanged();
    }
}

public ObservableCollection<UndoableCommand> RedoStack
{
    get { return _redoStack; }
    set
    {
        _redoStack = value;
        OnPropertyChanged();
    }
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(CodeTextboxHost), new PropertyMetadata("", new PropertyChangedCallback(
(d, e) =>
{
    var textBoxHost = d as CodeTextboxHost;
    if (textBoxHost != null && textBoxHost._innerTextbox != null)
    {
        textBoxHost._innerTextbox.Text = textBoxHost.GetValue(e.Property) as string;
    }
}), null));

public static readonly DependencyProperty HistoryProperty = DependencyProperty.Register("History", typeof(LimitedStack<UndoableCommand>), typeof(CodeTextboxHost), new PropertyMetadata(new LimitedStack<UndoableCommand>(200), new PropertyChangedCallback(
    (d, e) =>
    {
        var textBoxHost = d as CodeTextboxHost;
        if (textBoxHost != null && textBoxHost._innerTextbox != null)
        {
            var history = textBoxHost.GetValue(e.Property) as LimitedStack<UndoableCommand>;
            if (history != null)
            {
                textBoxHost._innerTextbox.TextSource.Manager.History = history;
                textBoxHost._innerTextbox.OnUndoRedoStateChanged();
            }
            else
            {
                textBoxHost._innerTextbox.ClearUndo();
            }
        }
    }), null));

public static readonly DependencyProperty RedoStackProperty = DependencyProperty.Register("RedoStack", typeof(Stack<UndoableCommand>), typeof(CodeTextboxHost), new PropertyMetadata(new Stack<UndoableCommand>(), new PropertyChangedCallback(
    (d, e) =>
    {
        var textBoxHost = d as CodeTextboxHost;
        if (textBoxHost != null && textBoxHost._innerTextbox != null)
        {
            var redoStack = textBoxHost.GetValue(e.Property) as Stack<UndoableCommand>;
            if (redoStack != null)
            {
                textBoxHost._innerTextbox.TextSource.Manager.RedoStack = redoStack;
                textBoxHost._innerTextbox.OnUndoRedoStateChanged();
            }
            else
            {
                textBoxHost._innerTextbox.ClearUndo();
            }
        }
    }), null));

public LimitedStack<UndoableCommand> History
{
    get { return (LimitedStack<UndoableCommand>) GetValue(HistoryProperty);}
    set { SetValue(HistoryProperty, value);}
}

public Stack<UndoableCommand> RedoStack
{
    get { return (Stack<UndoableCommand>) GetValue(RedoStackProperty); }
    set { SetValue(RedoStackProperty, value);}
}

public CodeTextboxHost()
{
    Child = _innerTextbox;
    _innerTextbox.Language = FastColoredTextBoxNS.Language.Custom;
    _innerTextbox.DescriptionFile = AppDomain.CurrentDomain.BaseDirectory + "SyntaxConfig\\MarkdownSyntaxHighlighting.xml";
    _innerTextbox.HighlightingRangeType = HighlightingRangeType.AllTextRange;
    _innerTextbox.TextChanged += _innerTextbox_TextChanged;
}

private void _innerTextbox_TextChanged(object sender, TextChangedEventArgs e)
{
    Text = _innerTextbox.Text;
    History = _innerTextbox.TextSource.Manager.History;
    RedoStack = _innerTextbox.TextSource.Manager.RedoStack; 
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(CodeTextboxHost), new PropertyMetadata("", new PropertyChangedCallback(
    (d, e) =>
    {
        var textBoxHost = d as CodeTextboxHost;
        if (textBoxHost != null && textBoxHost._innerTextbox != null)
        {
            textBoxHost._innerTextbox.Text = textBoxHost.GetValue(e.Property) as string;
        }
    }), null));

public static readonly DependencyProperty HistoryProperty = DependencyProperty.Register("History", typeof(ObservableCollection<UndoableCommand>), typeof(CodeTextboxHost), new PropertyMetadata(new ObservableCollection<UndoableCommand>(), new PropertyChangedCallback(
    (d, e) =>
    {
        var textBoxHost = d as CodeTextboxHost;
        if (textBoxHost != null && textBoxHost._innerTextbox != null)
        {
            var history = textBoxHost.GetValue(e.Property) as ObservableCollection<UndoableCommand>;
            if (history != null)
            {
                textBoxHost._innerTextbox.TextSource.Manager.History = history.ToLimitedStack(200);
                textBoxHost._innerTextbox.OnUndoRedoStateChanged();
            }
            else
            {
                textBoxHost._innerTextbox.ClearUndo();
            }
        }
    }), null));

public static readonly DependencyProperty RedoStackProperty = DependencyProperty.Register("RedoStack", typeof(ObservableCollection<UndoableCommand>), typeof(CodeTextboxHost), new PropertyMetadata(new ObservableCollection<UndoableCommand>(), new PropertyChangedCallback(
    (d, e) =>
    {
        var textBoxHost = d as CodeTextboxHost;
        if (textBoxHost != null && textBoxHost._innerTextbox != null)
        {
            var redoStack = textBoxHost.GetValue(e.Property) as ObservableCollection<UndoableCommand>;
            if (redoStack != null)
            {
                textBoxHost._innerTextbox.TextSource.Manager.RedoStack = redoStack.ToStack();
                textBoxHost._innerTextbox.OnUndoRedoStateChanged();
            }
            else
            {
                textBoxHost._innerTextbox.ClearUndo();
            }
        }
    }), null));

public ObservableCollection<UndoableCommand> History
{
    get { return (ObservableCollection<UndoableCommand>) GetValue(HistoryProperty);}
    set { SetValue(HistoryProperty, value);}
}

public ObservableCollection<UndoableCommand> RedoStack
{
    get { return (ObservableCollection<UndoableCommand>) GetValue(RedoStackProperty); }
    set { SetValue(RedoStackProperty, value);}
}

public string Text
{
    get { return (string)GetValue(TextProperty); }
    set { SetValue(TextProperty, value); }
}

public bool WordWrap
{
    get { return (bool)GetValue(WordWrapProperty); }
    set { SetValue(WordWrapProperty, value); }
}

public CodeTextboxHost()
{
    Child = _innerTextbox;
    _innerTextbox.Language = FastColoredTextBoxNS.Language.Custom;
    _innerTextbox.DescriptionFile = AppDomain.CurrentDomain.BaseDirectory + "SyntaxConfig\\MarkdownSyntaxHighlighting.xml";
    _innerTextbox.HighlightingRangeType = HighlightingRangeType.AllTextRange;
    _innerTextbox.TextChanged += _innerTextbox_TextChanged;
}

private void _innerTextbox_TextChanged(object sender, TextChangedEventArgs e)
{
    Text = _innerTextbox.Text;
    History = _innerTextbox.TextSource.Manager.History.ToOveObservableCollection();
    RedoStack = _innerTextbox.TextSource.Manager.RedoStack.ToObservableCollection();
}
public static readonly DependencyProperty HistoryProperty = DependencyProperty.Register("History", typeof(IEnumerable<UndoableCommand>), typeof(CodeTextboxHost), new FrameworkPropertyMetadata(new ObservableCollection<UndoableCommand>(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(
    (d, e) =>
    {
        var textBoxHost = d as CodeTextboxHost;
        if (textBoxHost != null && textBoxHost._innerTextbox != null)
        {
            var history = textBoxHost.GetValue(e.Property) as ObservableCollection<UndoableCommand>;
            if (history != null)
            {
                textBoxHost._innerTextbox.TextSource.Manager.History = history.ToLimitedStack(200);
                textBoxHost._innerTextbox.OnUndoRedoStateChanged();
            }
            else
            {
                textBoxHost._innerTextbox.ClearUndo();
            }
        }
    }), null));

public static readonly DependencyProperty RedoStackProperty = DependencyProperty.Register("RedoStack", typeof(IEnumerable<UndoableCommand>), typeof(CodeTextboxHost), new FrameworkPropertyMetadata(new ObservableCollection<UndoableCommand>(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(
    (d, e) =>
    {
        var textBoxHost = d as CodeTextboxHost;
        if (textBoxHost != null && textBoxHost._innerTextbox != null)
        {
            var redoStack = textBoxHost.GetValue(e.Property) as ObservableCollection<UndoableCommand>;
            if (redoStack != null)
            {
                textBoxHost._innerTextbox.TextSource.Manager.RedoStack = redoStack.ToStack();
                textBoxHost._innerTextbox.OnUndoRedoStateChanged();
            }
            else
            {
                textBoxHost._innerTextbox.ClearUndo();
            }
        }
    }), null));

public ObservableCollection<UndoableCommand> History
{
    get { return (ObservableCollection<UndoableCommand>) GetValue(HistoryProperty);}
    set { SetCurrentValue(HistoryProperty, new ObservableCollection<UndoableCommand>(value));}
}

public ObservableCollection<UndoableCommand> RedoStack
{
    get { return (ObservableCollection<UndoableCommand>) GetValue(RedoStackProperty); }
    set { SetCurrentValue(RedoStackProperty, new ObservableCollection<UndoableCommand>(value));}
}