├── .gitignore ├── README.md ├── SmithHtmlEditor.Demo ├── App.xaml ├── App.xaml.cs ├── BindingTestWindow.xaml ├── BindingTestWindow.xaml.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Resources │ ├── Resource.Designer.cs │ └── Resource.resx └── SmithHtmlEditor.Demo.csproj ├── SmithHtmlEditor.sln ├── SmithHtmlEditor ├── Extensions │ ├── ColorExtension.cs │ ├── FrameworkElementExtension.cs │ ├── HtmlEditingExtension.cs │ └── HtmlExtension.cs ├── Features │ ├── AttachedBehaviors.cs │ ├── HtmlEditingCommands.cs │ └── ValueConverter.cs ├── Models │ ├── Enum.cs │ ├── FontSize.cs │ ├── HtmlDocument.cs │ ├── HtmlObject.cs │ ├── OptionObject.cs │ └── WordCounter.cs ├── Resources │ ├── Images │ │ ├── ZoomIn.png │ │ ├── ZoomOut.png │ │ ├── bold.png │ │ ├── browser.png │ │ ├── center.png │ │ ├── code.png │ │ ├── copy.png │ │ ├── cut.png │ │ ├── del.png │ │ ├── erase.png │ │ ├── error.png │ │ ├── find.png │ │ ├── fontcolor.png │ │ ├── goto.png │ │ ├── help.png │ │ ├── htmlcode.png │ │ ├── hyperlink.png │ │ ├── image.png │ │ ├── indent.png │ │ ├── italic.png │ │ ├── left.png │ │ ├── linecolor.png │ │ ├── listbullets.png │ │ ├── listnumbered.png │ │ ├── new.png │ │ ├── open.png │ │ ├── outdent.png │ │ ├── paste.png │ │ ├── print.png │ │ ├── prop.png │ │ ├── redo.png │ │ ├── refresh.png │ │ ├── replace.png │ │ ├── right.png │ │ ├── save.png │ │ ├── saveas.png │ │ ├── spelling.png │ │ ├── stretch.png │ │ ├── subscript.png │ │ ├── superscript.png │ │ ├── table.png │ │ ├── underline.png │ │ ├── undo.png │ │ └── window.png │ ├── UiText.Designer.cs │ ├── UiText.en-US.resx │ ├── UiText.hu-HU.resx │ ├── UiText.resx │ └── UiText.zh-CN.resx ├── SmithHtmlEditor.csproj ├── Views │ ├── ColorPicker.xaml │ ├── ColorPicker.xaml.cs │ ├── HtmlEditor.xaml │ ├── HtmlEditor.xaml.cs │ ├── HyperlinkDialog.xaml │ ├── HyperlinkDialog.xaml.cs │ ├── ImageDialog.xaml │ ├── ImageDialog.xaml.cs │ ├── TableDialog.xaml │ └── TableDialog.xaml.cs ├── obj │ └── wappublish │ │ ├── win-x64 │ │ ├── SmithHtmlEditor.csproj.nuget.cache │ │ ├── SmithHtmlEditor.csproj.nuget.dgspec.json │ │ ├── SmithHtmlEditor.csproj.nuget.g.props │ │ ├── SmithHtmlEditor.csproj.nuget.g.targets │ │ └── project.assets.json │ │ └── win-x86 │ │ ├── SmithHtmlEditor.csproj.nuget.cache │ │ ├── SmithHtmlEditor.csproj.nuget.dgspec.json │ │ ├── SmithHtmlEditor.csproj.nuget.g.props │ │ ├── SmithHtmlEditor.csproj.nuget.g.targets │ │ └── project.assets.json ├── smithhtmleditor.config.xml └── smithhtmleditor.stylesheet.css └── clean.bat /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | Releases/*.apk 7 | Releases/*.ipa 8 | Softwares/ 9 | Databases/ 10 | 11 | # User-specific files 12 | *.suo 13 | *.user 14 | *.userosscache 15 | *.sln.docstates 16 | 17 | # User-specific files (MonoDevelop/Xamarin Studio) 18 | *.userprefs 19 | 20 | # Build results 21 | [Dd]ebug/ 22 | [Dd]ebugPublic/ 23 | [Rr]elease/ 24 | x64/ 25 | x86/ 26 | bld/ 27 | [Bb]in/ 28 | [Oo]bj/ 29 | [Ll]og/ 30 | 31 | # Visual Studio 2015/2017 cache/options directory 32 | .vs/ 33 | # Uncomment if you have tasks that create the project's static files in wwwroot 34 | #wwwroot/ 35 | 36 | # Visual Studio 2017 auto generated files 37 | Generated\ Files/ 38 | 39 | # MSTest test Results 40 | [Tt]est[Rr]esult*/ 41 | [Bb]uild[Ll]og.* 42 | 43 | # NUNIT 44 | *.VisualState.xml 45 | TestResult.xml 46 | 47 | # Build Results of an ATL Project 48 | [Dd]ebugPS/ 49 | [Rr]eleasePS/ 50 | dlldata.c 51 | 52 | # Benchmark Results 53 | BenchmarkDotNet.Artifacts/ 54 | 55 | # .NET Core 56 | project.lock.json 57 | project.fragment.lock.json 58 | artifacts/ 59 | **/Properties/launchSettings.json 60 | 61 | # StyleCop 62 | StyleCopReport.xml 63 | 64 | # Files built by Visual Studio 65 | *_i.c 66 | *_p.c 67 | *_i.h 68 | *.ilk 69 | *.meta 70 | *.obj 71 | *.iobj 72 | *.pch 73 | *.pdb 74 | *.ipdb 75 | *.pgc 76 | *.pgd 77 | *.rsp 78 | *.sbr 79 | *.tlb 80 | *.tli 81 | *.tlh 82 | *.tmp 83 | *.tmp_proj 84 | *.log 85 | *.vspscc 86 | *.vssscc 87 | .builds 88 | *.pidb 89 | *.svclog 90 | *.scc 91 | 92 | # Chutzpah Test files 93 | _Chutzpah* 94 | 95 | # Visual C++ cache files 96 | ipch/ 97 | *.aps 98 | *.ncb 99 | *.opendb 100 | *.opensdf 101 | *.sdf 102 | *.cachefile 103 | *.VC.db 104 | *.VC.VC.opendb 105 | 106 | # Visual Studio profiler 107 | *.psess 108 | *.vsp 109 | *.vspx 110 | *.sap 111 | 112 | # Visual Studio Trace Files 113 | *.e2e 114 | 115 | # TFS 2012 Local Workspace 116 | $tf/ 117 | 118 | # Guidance Automation Toolkit 119 | *.gpState 120 | 121 | # ReSharper is a .NET coding add-in 122 | _ReSharper*/ 123 | *.[Rr]e[Ss]harper 124 | *.DotSettings.user 125 | 126 | # JustCode is a .NET coding add-in 127 | .JustCode 128 | 129 | # TeamCity is a build add-in 130 | _TeamCity* 131 | 132 | # DotCover is a Code Coverage Tool 133 | *.dotCover 134 | 135 | # AxoCover is a Code Coverage Tool 136 | .axoCover/* 137 | !.axoCover/settings.json 138 | 139 | # Visual Studio code coverage results 140 | *.coverage 141 | *.coveragexml 142 | 143 | # NCrunch 144 | _NCrunch_* 145 | .*crunch*.local.xml 146 | nCrunchTemp_* 147 | 148 | # MightyMoose 149 | *.mm.* 150 | AutoTest.Net/ 151 | 152 | # Web workbench (sass) 153 | .sass-cache/ 154 | 155 | # Installshield output folder 156 | [Ee]xpress/ 157 | 158 | # DocProject is a documentation generator add-in 159 | DocProject/buildhelp/ 160 | DocProject/Help/*.HxT 161 | DocProject/Help/*.HxC 162 | DocProject/Help/*.hhc 163 | DocProject/Help/*.hhk 164 | DocProject/Help/*.hhp 165 | DocProject/Help/Html2 166 | DocProject/Help/html 167 | 168 | # Click-Once directory 169 | publish/ 170 | 171 | # Publish Web Output 172 | *.[Pp]ublish.xml 173 | *.azurePubxml 174 | # Note: Comment the next line if you want to checkin your web deploy settings, 175 | # but database connection strings (with potential passwords) will be unencrypted 176 | *.pubxml 177 | *.publishproj 178 | 179 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 180 | # checkin your Azure Web App publish settings, but sensitive information contained 181 | # in these scripts will be unencrypted 182 | PublishScripts/ 183 | 184 | # NuGet Packages 185 | *.nupkg 186 | # The packages folder can be ignored because of Package Restore 187 | **/[Pp]ackages/* 188 | # except build/, which is used as an MSBuild target. 189 | !**/[Pp]ackages/build/ 190 | # Uncomment if necessary however generally it will be regenerated when needed 191 | #!**/[Pp]ackages/repositories.config 192 | # NuGet v3's project.json files produces more ignorable files 193 | *.nuget.props 194 | *.nuget.targets 195 | 196 | # Microsoft Azure Build Output 197 | csx/ 198 | *.build.csdef 199 | 200 | # Microsoft Azure Emulator 201 | ecf/ 202 | rcf/ 203 | 204 | # Windows Store app package directories and files 205 | AppPackages/ 206 | BundleArtifacts/ 207 | Package.StoreAssociation.xml 208 | _pkginfo.txt 209 | *.appx 210 | 211 | # Visual Studio cache files 212 | # files ending in .cache can be ignored 213 | *.[Cc]ache 214 | # but keep track of directories ending in .cache 215 | !*.[Cc]ache/ 216 | 217 | # Others 218 | ClientBin/ 219 | ~$* 220 | *~ 221 | *.dbmdl 222 | *.dbproj.schemaview 223 | *.jfm 224 | *.pfx 225 | *.publishsettings 226 | orleans.codegen.cs 227 | 228 | # Including strong name files can present a security risk 229 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 230 | #*.snk 231 | 232 | # Since there are multiple workflows, uncomment next line to ignore bower_components 233 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 234 | #bower_components/ 235 | 236 | # RIA/Silverlight projects 237 | Generated_Code/ 238 | 239 | # Backup & report files from converting an old project file 240 | # to a newer Visual Studio version. Backup files are not needed, 241 | # because we have git ;-) 242 | _UpgradeReport_Files/ 243 | Backup*/ 244 | UpgradeLog*.XML 245 | UpgradeLog*.htm 246 | ServiceFabricBackup/ 247 | *.rptproj.bak 248 | 249 | # SQL Server files 250 | *.mdf 251 | *.ldf 252 | *.ndf 253 | 254 | # Business Intelligence projects 255 | *.rdl.data 256 | *.bim.layout 257 | *.bim_*.settings 258 | *.rptproj.rsuser 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush 299 | .cr/ 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | /Source/LMA.Android/Resources/Resource.designer.cs 336 | /Dependences/XAML to HTML Conversion Demo.zip 337 | /Dependences/smithhtmleditor.zip 338 | /Scripts/nuget/Nuget API key.txt 339 | /Scripts/nuget/publish.bat 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wpf-html-editor # 2 | license : MIT 3 | framework : WPF 4 | 5 | WYSIWYG rich text editor which enables writing content directly inside of wpf applications. 6 | 7 | Read more on html editor 8 | 9 | ![wpf-html-editor](https://www.cmarix.com/git/DotNet/wpf-html-editor.gif) 10 | 11 | ## Installation ## 12 | Click here to get html editor related DLL. Download DLL from this link and add reference of this DLL into your WPF application. 13 | 14 | ## Steps ## 15 | 16 | 17 | 1. Add below assembly in your XAML page like below: 18 | 19 | xmlns:smith="clr-namespace:Smith.WPF.HtmlEditor;assembly=Smith.WPF.HtmlEditor" 20 | 21 | 2. Insert editor using assembly name in your XAML page like below: 22 | 23 | 24 | 25 | 26 | ## Let us know! ## 27 | I’d be really happy if you sent us links to your projects where you use our component. Just send an email to [adambarath@msn.com](mailto:adambarath@msn.com "adambarath@msn.com") and do let us know if you have any questions or suggestion regarding wpf. 28 | Skype: @adambarath 29 | 30 | ## Updates ## 31 | 32 | 2020/05/06 33 | 1. extend target frameworks to netcoreapp3.0;netcoreapp3.1;net461;net462;net47;net471;net472;net48 34 | 2. add pre-build event to do dotnet restore. Issue description at https://stackoverflow.com/questions/48440223/assets-file-project-assets-json-not-found-run-a-nuget-package-restore 35 | 36 | 2019/10/31 37 | 1. update to NetCore 3.0 38 | 39 | 2011/05/02 40 | 1. Add a dependency property named BindingContent to support binding html content to the editor. This property raise update notification via the StatusTextChanged event of the webbrowser control. A new window named BindingTestWindow in SmithHtmlEditor.Demo show how this property works. 41 | 2. A stylesheet is load from the file "smithhtmleditor.stylesheet.css" to set the default style of the editing document when the control is initializing. This can help us to set how the document looks. 42 | 3. Use the xml file "smithhtmleditor.config.xml" to setup the fonts used in the control. So we can configurate the fonts we need. 43 | 4. Update the appearance of the editor under source mode. 44 | 45 | 2011/01/23 46 | 1. Add HtmlDocument class and HtmlDocument.Range class for document editing instead of directly operating IHTMLDocument2 interface and System.Windows.Forms.HtmlDocument object. 47 | 2. Update HtmlEditingExtension class to extension methods for HtmlDocument object. And some methods were moved into HtmlDocument class. 48 | 3. Fix a bug in HtmlEditor.WordCount property. 49 | 4. Update the HtmlEditor.ContentText property as a get-only property. 50 | 5. The HtmlEditor.Document property is changed from type System.Windows.Forms.HtmlDocument to Smith.WPF.HtmlEditor.HtmlDocument. 51 | 6. Add editing methods for HtmlEditor class. 52 | 7. Add DocumentReady event for HtmlEditor class. This event will be raised after the document is ready to use. And it provides a way to load initial content to editor. See the demo. 53 | 8. Add DocumentStateChanged event for HtmlEditor class to notify the change of document state. 54 | 55 | 2010/11/20 56 | Upgraded the word counting algorithm and fixed a bug in color selecting. 57 | 58 | 2010/10/19 59 | Globlization and localization feature is added into this version. 60 | 61 | 2010/10/17 62 | It is a preview version for test and provides basic functions for common use. 63 | 64 | 65 | ## License ## 66 | 67 | MIT License 68 | 69 | Permission is hereby granted, free of charge, to any person obtaining a copy 70 | of this software and associated documentation files (the "Software"), to deal 71 | in the Software without restriction, including without limitation the rights 72 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 73 | copies of the Software, and to permit persons to whom the Software is 74 | furnished to do so, subject to the following conditions: 75 | 76 | The above copyright notice and this permission notice shall be included in all 77 | copies or substantial portions of the Software. 78 | 79 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 80 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 81 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 82 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 83 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 84 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 85 | SOFTWARE. 86 | -------------------------------------------------------------------------------- /SmithHtmlEditor.Demo/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /SmithHtmlEditor.Demo/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Windows; 7 | using System.Globalization; 8 | using System.Threading; 9 | using System.Windows.Markup; 10 | 11 | namespace Smith.WPF.HtmlEditor.Demo 12 | { 13 | /// 14 | /// App.xaml 的交互逻辑 15 | /// 16 | public partial class App : Application 17 | { 18 | protected override void OnStartup(StartupEventArgs e) 19 | { 20 | CultureInfo culture = null; 21 | 22 | if (culture != null) 23 | { 24 | Thread.CurrentThread.CurrentCulture = culture; 25 | Thread.CurrentThread.CurrentUICulture = culture; 26 | } 27 | 28 | FrameworkElement.LanguageProperty.OverrideMetadata( 29 | typeof(FrameworkElement), new FrameworkPropertyMetadata( 30 | XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag))); 31 | 32 | base.OnStartup(e); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SmithHtmlEditor.Demo/BindingTestWindow.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 11 | 12 | 13 | 15 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SmithHtmlEditor.Demo/BindingTestWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Data; 8 | using System.Windows.Documents; 9 | using System.Windows.Input; 10 | using System.Windows.Media; 11 | using System.Windows.Media.Imaging; 12 | using System.Windows.Shapes; 13 | 14 | namespace Smith.WPF.HtmlEditor.Demo 15 | { 16 | /// 17 | /// BindingTestWindow.xaml 的交互逻辑 18 | /// 19 | public partial class BindingTestWindow : Window 20 | { 21 | public BindingTestWindow() 22 | { 23 | InitializeComponent(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SmithHtmlEditor.Demo/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 19 | 23 | 24 | 25 | 29 | 30 | 32 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 144 | 147 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /SmithHtmlEditor/Views/ImageDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Data; 8 | using System.Windows.Documents; 9 | using System.Windows.Input; 10 | using System.Windows.Media; 11 | using System.Windows.Media.Imaging; 12 | using System.Windows.Shapes; 13 | using System.Net; 14 | using System.ComponentModel; 15 | using System.Collections.ObjectModel; 16 | using System.IO; 17 | 18 | namespace Smith.WPF.HtmlEditor 19 | { 20 | /// 21 | /// ImageDialog.xaml 的交互逻辑 22 | /// 23 | public partial class ImageDialog : Window 24 | { 25 | ImageObject bindingContext; 26 | 27 | public ImageDialog() 28 | { 29 | InitializeComponent(); 30 | InitAlignmentItems(); 31 | InitBindingContext(); 32 | InitEvents(); 33 | } 34 | 35 | public ImageObject Model 36 | { 37 | get { return bindingContext; } 38 | private set 39 | { 40 | bindingContext = value; 41 | DataContext = bindingContext; 42 | } 43 | } 44 | 45 | void InitBindingContext() 46 | { 47 | Model = new ImageObject 48 | { 49 | ImageUrl = "http://", 50 | Alignment = ImageAlignment.Default 51 | }; 52 | } 53 | 54 | void InitAlignmentItems() 55 | { 56 | List ls = new List(); 57 | ls.Add(ImageAlignment.Default); 58 | ls.Add(ImageAlignment.Left); 59 | ls.Add(ImageAlignment.Right); 60 | ls.Add(ImageAlignment.Top); 61 | ls.Add(ImageAlignment.Center); 62 | ls.Add(ImageAlignment.Bottom); 63 | ImageAlignmentSelection.ItemsSource = new ReadOnlyCollection(ls); 64 | ImageAlignmentSelection.DisplayMemberPath = "Text"; 65 | } 66 | 67 | void InitEvents() 68 | { 69 | RefreshButton.Click += new RoutedEventHandler(RefreshButton_Click); 70 | BrowseButton.Click += new RoutedEventHandler(BrowseButton_Click); 71 | ResizeSlider.ValueChanged += new RoutedPropertyChangedEventHandler(ResizeSlider_ValueChanged); 72 | ZoomInButton.Click += new RoutedEventHandler(ZoomInButton_Click); 73 | ZoomOutButton.Click += new RoutedEventHandler(ZoomOutButton_Click); 74 | OkayButton.Click += new RoutedEventHandler(OkayButton_Click); 75 | CancelButton.Click += new RoutedEventHandler(CancelButton_Click); 76 | 77 | ScrollViewContentDragable.SetEnable(PreviewScroll, true); 78 | } 79 | 80 | void CancelButton_Click(object sender, RoutedEventArgs e) 81 | { 82 | e.Handled = true; 83 | this.Close(); 84 | } 85 | 86 | void OkayButton_Click(object sender, RoutedEventArgs e) 87 | { 88 | e.Handled = true; 89 | if (System.Windows.Interop.ComponentDispatcher.IsThreadModal) this.DialogResult = true; 90 | this.Close(); 91 | } 92 | 93 | void ZoomOutButton_Click(object sender, RoutedEventArgs e) 94 | { 95 | double val = ResizeSlider.Value - 10; 96 | if (val < 0) val = 1; 97 | ResizeSlider.Value = val; 98 | } 99 | 100 | void ZoomInButton_Click(object sender, RoutedEventArgs e) 101 | { 102 | double val = ResizeSlider.Value + 10; 103 | if (val > 200) val = 200; 104 | ResizeSlider.Value = val; 105 | } 106 | 107 | void ResizeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) 108 | { 109 | double p = e.NewValue / 100; 110 | bindingContext.Width = Convert.ToInt32(Math.Round(p * bindingContext.OriginalWidth)); 111 | bindingContext.Height = Convert.ToInt32(Math.Round(p * bindingContext.OriginalHeight)); 112 | } 113 | 114 | void BrowseButton_Click(object sender, RoutedEventArgs e) 115 | { 116 | using (System.Windows.Forms.OpenFileDialog dialog = 117 | new System.Windows.Forms.OpenFileDialog()) 118 | { 119 | dialog.Filter = "所有格式|*.jpg;*.jpeg;*.png;*gif|JPEG|*.jpg;*.jpeg|PNG|*.png|GIF|*.gif"; 120 | dialog.FilterIndex = 0; 121 | if (System.Windows.Forms.DialogResult.OK == dialog.ShowDialog()) 122 | { 123 | UrlText.Text = dialog.FileName; 124 | LoadImage(dialog.FileName); 125 | } 126 | } 127 | } 128 | 129 | void RefreshButton_Click(object sender, RoutedEventArgs e) 130 | { 131 | if(!string.IsNullOrEmpty(UrlText.Text)) LoadImageAsyn(UrlText.Text); 132 | } 133 | 134 | /// 135 | /// 加载图像,用于加载本地图像 136 | /// 137 | void LoadImage(string uri) 138 | { 139 | StatusPrompt.Content = "正在加载"; 140 | PreviewImage.Source = null; 141 | bindingContext.Image = null; 142 | 143 | // 加载图像 144 | Uri u = new Uri(uri, UriKind.RelativeOrAbsolute); 145 | BitmapImage img = new BitmapImage(u); 146 | PreviewImage.Source = img; 147 | 148 | // 更新绑定上下文 149 | bindingContext.ImageUrl = u.ToString(); 150 | bindingContext.Image = img; 151 | bindingContext.OriginalWidth = img.PixelWidth; 152 | bindingContext.OriginalHeight = img.PixelHeight; 153 | 154 | ResizeSlider.Value = 100; 155 | ScrollToCenter(); 156 | } 157 | 158 | /// 159 | /// 异步加载图像,用于加载网络上的图像 160 | /// 161 | void LoadImageAsyn(string uri) 162 | { 163 | StatusPrompt.Content = "正在下载"; 164 | PreviewImage.Source = null; 165 | bindingContext.Image = null; 166 | TopContentArea.IsEnabled = false; 167 | 168 | // 异步下载图像 169 | Uri u = new Uri(uri, UriKind.RelativeOrAbsolute); 170 | BitmapImage img = new BitmapImage(u); 171 | img.DownloadCompleted += new EventHandler(ImageDownloadCompleted); 172 | img.DownloadFailed += new EventHandler(ImageDownloadFailed); 173 | } 174 | 175 | /// 176 | /// 图像下载完成时调用 177 | /// 178 | void ImageDownloadCompleted(object sender, EventArgs e) 179 | { 180 | // 异步下载图像完成 181 | StatusPrompt.Content = "下载完成"; 182 | TopContentArea.IsEnabled = true; 183 | BitmapImage img = (BitmapImage)sender; 184 | PreviewImage.Source = img; 185 | 186 | // 更新绑定上下文 187 | bindingContext.ImageUrl = img.UriSource.ToString(); 188 | bindingContext.Image = img; 189 | bindingContext.OriginalWidth = img.PixelWidth; 190 | bindingContext.OriginalHeight = img.PixelHeight; 191 | 192 | ResizeSlider.Value = 100; 193 | ScrollToCenter(); 194 | } 195 | 196 | /// 197 | /// 图像下载失败时调用 198 | /// 199 | void ImageDownloadFailed(object sender, ExceptionEventArgs e) 200 | { 201 | // 异步下载图像失败 202 | StatusPrompt.Content = "无法加载图像"; 203 | TopContentArea.IsEnabled = true; 204 | 205 | // 更新绑定上下文 206 | bindingContext.Image = null; 207 | bindingContext.Width = 0; 208 | bindingContext.Height = 0; 209 | bindingContext.OriginalWidth = 0; 210 | bindingContext.OriginalHeight = 0; 211 | } 212 | 213 | void ScrollToCenter() 214 | { 215 | if (PreviewImage.Width > PreviewScroll.ViewportWidth) 216 | { 217 | PreviewScroll.ScrollToHorizontalOffset((PreviewImage.Width - PreviewScroll.ViewportWidth) / 2); 218 | } 219 | 220 | if (PreviewImage.Height > PreviewScroll.ViewportHeight) 221 | { 222 | PreviewScroll.ScrollToVerticalOffset((PreviewImage.Height - PreviewScroll.ViewportHeight) / 2); 223 | } 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /SmithHtmlEditor/Views/TableDialog.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 13 | 16 | 20 | 24 | 30 | 31 | 32 | 33 | 34 | 35 |